{
"cells": [
{
"cell_type": "markdown",
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": []
},
"source": [
"# `MinDriver` steps\n",
"\n",
"In this tutorial, we show how we can save individual steps during minimisation as well as how we can analyse them. We are going to minimise a simple system object. For details on how to define a system object, please have a look at other tutorials."
]
},
{
"cell_type": "code",
"execution_count": 1,
"metadata": {},
"outputs": [],
"source": [
"import discretisedfield as df\n",
"import micromagneticmodel as mm\n",
"\n",
"import oommfc as mc\n",
"\n",
"region = df.Region(p1=(-50e-9, -50e-9, 0), p2=(50e-9, 50e-9, 10e-9))\n",
"mesh = df.Mesh(region=region, cell=(5e-9, 5e-9, 5e-9))\n",
"\n",
"system = mm.System(name=\"mindriver_steps\")\n",
"\n",
"system.energy = mm.Zeeman(H=(0, 0, 1e5))\n",
"system.m = df.Field(mesh, nvdim=3, value=(1, 0, 0), norm=1.1e6)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We now have a system object and we can minimise it using `MinDriver`. By default, `MinDriver` saves only the data of the last step in the relexation. However, if we want to save all individual steps in between, we have to pass `output_step=True` to the `drive` method."
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Running OOMMF (ExeOOMMFRunner)[2023/10/18 12:39]... (0.4 s)\n"
]
}
],
"source": [
"md = mc.MinDriver()\n",
"md.drive(system, output_step=True)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"If we have a look at the table, we can see that multiple steps are saved:"
]
},
{
"cell_type": "code",
"execution_count": 3,
"metadata": {
"tags": [
"nbval-ignore-output"
]
},
"outputs": [
{
"data": {
"text/html": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"system.table.mpl(y=[\"E\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"By fecault, iteration is showed on the $x$-axis. We can change that by passing `x` variable. For example:"
]
},
{
"cell_type": "code",
"execution_count": 5,
"metadata": {},
"outputs": [
{
"data": {
"image/png": "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3KlXXnlFF198sb766ivvFugF/bom6eJzO6iwsIwHNgAAAHiZqedITZo0Sa+//rqSk5ObdL5hGHr00Ud19tlna8SIEV6uDgAAAIHO1FeGL7vssjM6f968edqwYYM+/PBDrVu3zjtFAQAAwDRMHYbPRE5OjmbOnKnbbrtNnTt3Pq0wbLVafDa71maz1vkV5kMPzY8emhv9Mz96aH6B3MOAC8NOp1P79u076TGxsbFKSUk5o/f5y1/+oqSkJN12222nfW5iYrTP59zGxUX69P3gffTQ/OihudE/86OH5heIPQy4MJyTk6PRo0ef9JgJEyboySefbPJ7fPHFF/riiy/05ptvKiws7LTPLygo8+mV4bi4SBUXV8jt5gY6M6KH5kcPzY3+mR89ND9/9NBuj27UcQEXhtPS0pSVldVsr19aWqrHHntMY8eOVe/evVVWViapetawJFVWVqqiokKRkQ3/zcXjMeTx8YMt3G4P0yRMjh6aHz00N/pnfvTQ/AKxhwEXhpvbpk2blJubq48++kgfffRRvf1jxoxRu3bttHTpUj9UBwAAAF8KujDcs2dPzZ07t972FStW6OWXX9azzz6rdu3a+aEyAAAA+Jppw7DD4ai3nKK4uFgbNmyQJNnt9trHKg8bNkxJSUmaN2+eYmNjNXDgwHqvV3PTXu/evQPqccwAAABoPqYNw7m5ubryyivrbFu5cqVWrlwpqe5Ndm63W2632+c1AgAAILBZDMPw7Z1gLcCRIyU+e6+QEKvs9mgex2xi9ND86KG50T/zo4fm548eJifHNuq4wJt8DAAAAPgIYRgAAABBizAMAACAoEUYBgAAQNAiDAMAACBoEYYBAAAQtAjDAAAACFqEYQAAAAQtHroBAACAoMWVYQAAAAQtwjAAAACCFmEYAAAAQYswDAAAgKBFGAYAAEDQIgwDAAAgaBGG/Wjr1q269dZbNWDAAPXr10/XX3+91qxZ02znwfua2otvvvlG11xzjfr166fMzExde+21WrZsmQ8qxs954+vpu+++U48ePfTrX/+6marEyTS1h+Xl5XryySd10UUXqW/fvhozZozeffddH1SM4zWlfx6PR++//76uvPJKDRw4UP369dPEiRP13nvv+ahq/NzWrVs1cuRIde/eXTt37mzUOWvWrNH111+v/v3765xzztGtt96qrVu3NnOl9RGG/WTfvn267rrrVFhYqKefflovv/yyYmJiNHnyZP30009ePw/e19ReLF26VDfddJNiYmI0e/ZsPfXUUwoPD9ett96qTz75xIefAN74enI4HPrDH/4gRrb7R1N76PF4dPvtt+u9997T1KlT9Y9//EN9+/bVH//4Ry1YsMCHnyC4NbV/Tz/9tB555BH17dtXs2fP1gsvvKBu3brp0Ucf1d///ncffgJI0ty5c3XVVVeptLS00ed8//33mjx5siIjI/XCCy/omWeeUXFxsa6//nrt37+/Gas9AQN+8bvf/c7o16+fkZ+fX7utqqrKGDp0qHHjjTd6/Tx4X1N7cdlllxnDhw83HA5H7bby8nIjMzPTuOaaa5qzZPyMN76eZs2aZQwePNiYOHGicf311zdTpWhIU3v40UcfGenp6cbHH39cZ/sNN9xg/OEPf2iucvEzTe3fgAEDjEmTJtXZ5vF4jEsvvdS4/PLLm6tcnMDq1auNPn36GO+9957x3HPPGenp6caOHTtOed71119vDB061Kiqqqrdlp+fb/Tr18/4/e9/35wl18OVYT8wDEOLFy/W+eefr8TExNrtYWFhGj58uFavXq3i4mKvnQfvO5MeTp06VdOnT1doaGjt9sjISHXo0EGHDx/2Sf3wztfTtm3b9I9//EP333+/oqKimrtk/MyZ9PCDDz5Q69atNXLkyDrb33jjDT322GPNWjeqnUn/wsLC6n3NWSwWxcTENGvNqC8hIUHvvPOOrrzyykafc/ToUX333XcaNmyYwsLCarcnJibqggsu0OLFi5uj1AYRhv3g4MGDKikpUbdu3ert69atmzwej7Zt2+a18+B9Te2FxWLR6NGjdd5559XZ7nQ6tXfvXrVv377ZakZdZ/r15PF49Mc//lFnn322rrjiiuYsFQ04kx7+9NNPOuecc2SxWJq7TDTgTPp30003adWqVXr//fdVUVGh8vJyzZs3T1u3btWNN97Y3KXjOOnp6erZs+dpnbNt2zYZhqH09PR6+7p27aqjR4/q0KFD3irxlEJ89k6olZ+fL0my2+319tVsqznGG+fB+7zdi9mzZ+vo0aO69tprvVMgTulMezhv3jxt2rRJCxcubJ4CcUpN7WFxcbGKi4vVunVrzZ07V2+++aYOHDiglJQUXX/99brxxhtls9mat3ic0dfgLbfcoqioKP35z3/WI488Iqn6/7DNmDFD48aNa6aK4S2N7X2bNm18Ug9h2A8cDock1flfAzVq/td5ZWWl186D93mzF++8847mzJmjiRMnavjw4d4rEid1Jj08fPiw/va3v+nWW29V586dm69InFRTe1heXi5J+uyzz3TWWWfp97//vcLCwrRo0SLNmDFDeXl5evDBB5uxckhn9jW4bNkyzZgxQ6NGjdK4cePkdDr1wQcf6I9//KPsdrsuuuii5iscZ6yqqkqS6iwXrOGPPEMY9oPw8HBJ1f9r/OdqvjlERkZ67Tx4n7d68fzzz2v27NkaO3as/vKXv3i3SJzUmfRw+vTpSklJ0W233dZ8BeKUmtrDmqu+TqdTr7zyiiIiIiRJgwcPVm5urt544w1NmTKlzjpWeF9T++dwOPTII4/o7LPP1lNPPVW7/Re/+IWuuOIKPfbYYz5fc4rTU/M1d6Le12zzZZ5hzbAfJCcnS5IKCgrq7cvLy6tzjDfOg/d5oxd/+tOfNHv2bE2ZMkVPPfWUQkL4u6kvNbWHn332mb788ks9/PDDcjqdKisrU1lZmdxut9xut8rKymp/kKN5NbWHCQkJstls6tWrV+0P5RoXXHCBXC6Xtm/f3gwV43hN7d+ePXt05MgRXXjhhfX2ZWZmKjs7myWDAS4pKUmSVFhYWG+fP/IMP339oHXr1rLb7crKyqq3LysrS6GhoSdcVN7U8+B9Z9qLWbNm6d1339UjjzyiG264oTlLRQOa2sMvv/xShmHo1ltvPeHrnnPOObrrrrt09913e71m1NXUHoaGhqpr164nDGFut7v2GDSvpvav5n+fu1yuevtqriryF9LA1r17d9lstgZ7n5ycrJSUFJ/Vw5VhPxkxYoS++eYbHTlypHZbeXm5Pv/8c1100UWKjo726nnwvqb2YvHixXr55Zd1//33E4T9rCk9vP322zV37tx6/2RkZCgjI0Nz585luoQPNfXrcPTo0dqwYUO9K8DLli1TZGSkevTo0ax1o1pT+te1a1dFRETo66+/rrdvzZo1Sk5OVuvWrZu1bpyZ2NhYnX/++fr000/rrA3OycnRqlWrNGrUKN8W5NOpxqh1+PBhIzMz05g4caLx5ZdfGitXrjRuvPFGo3///sb27dsNw6geZJ2RkWG88847p3UefKMpPXQ6ncall15qXHLJJcZPP/1krF+/vt4/xw8gR/Nq6tfhiVx//fU8dMMPmtrDkpISY/jw4cZFF11kfPzxx8Y333xjPPTQQ0Z6eroxe/Zsf32coNPU/s2ePdtIT083HnzwQWPZsmXGV199Zdx7771Genq6MXfuXH99nKCUnZ1d+/Pr0UcfNdLT041PP/20zs+0BQsWGBkZGcaKFStqz9u8ebPRt29fY/LkycbXX39tLF261Bg/frxx/vnnG0eOHPHpZ2CZhJ+kpqbqX//6l5566ilNmzZNhmGof//+evPNN9W1a1dJ1QPJ3W63PB7PaZ0H32hKDw8fPqzs7GxJ0lVXXXXC112yZInS0tJ88yGCXFO/DhE4mtrDmJgYvf3223r66ac1ffp0lZaWqlOnTnr88ccb/NqE9zW1f3fddZdSU1M1d+5cffLJJ7JYLOrWrZtmzZql0aNH++vjBKXnn3++3iPM77nnntrfL1myRB6Pp14PMzIy9Prrr2vmzJm64447ZLPZNHjwYM2aNat2TbGvWAzDMHz6jgAAAECAYM0wAAAAghZhGAAAAEGLMAwAAICgRRgGAABA0CIMAwAAIGgRhgEAABC0CMMAAAAIWoRhAAAABC3CMAAAAIIWYRgAcFpmzZqlnj17asWKFXrggQd09tlna8uWLf4uCwCahMcxAwAa7dNPP9W9996r++67T1OnTlVVVZWuuOIKlZaWauHChYqPj/d3iQBwWgjDAIBGKSgo0MiRI5WUlKSPPvpINptNkrR+/XpdffXVGjdunGbMmOHnKgHg9LBMAgDQKC+++KKKiop055131gZhSerbt69GjBihhQsXslwCgOkQhgHApB566CF1795dW7Zs0Zw5c3TJJZeoT58+Gj58uN577z1J0sqVKzVp0iT1799fF110kR588EGVlpbK4XBo7Nix6t27t7Zv317ndQsKCjRo0CANHjxYeXl5kqSKigq9//77ateunUaNGlWvlmuuuUaGYejNN99s/g8OAF5EGAYAk/v73/+u5cuX6/bbb9c999yjgoICPfroo3r99df10EMP6Ze//KUeeeQRtW3bVgsXLtTf/vY3hYWF6amnnpIkPfroo/J4PLWv98QTT+jo0aN64oknlJSUJElas2aNKioqdOGFF8pqrf+jY8CAAYqOjtbnn38ul8vlmw8OAF5AGAYAk9u+fbtef/11XX311brlllt0yy23SJJmzJihV199VbfccouuuuoqPfvss7JYLPryyy8lST169NB9992ndevW6e2335YkLVu2TIsWLdKkSZN0ySWX1L7HypUrJUlDhgw5YQ2hoaHKzMxUaWkpSyUAmAphGABMbsKECQoJCan9c0ZGhiSpX79+6t69e+321NRUtWrVSkeOHKndNnnyZGVmZmrWrFnavn27pk+fro4dO+qhhx6q8x579uyRJHXq1KnBOjp37ixJ2r9//xl/JgDwFcIwAJhcu3bt6vw5PDz8hNtr9h2/jMFqtWrGjBmy2Wy6+uqrlZOTo6eeekpRUVF1zisoKJAkJSYmNlhHzb6aYwHADAjDAGByYWFhJ9weGhraqPPbtm2rIUOGqLy8XN27d1efPn3qHVNSUiJJio2NbfB14uLi6hwLAGZAGAaAILdy5Up9+umnSk9P16ZNm/TWW2/VO6YmBJ8s6BYXF9c5FgDMgDAMAEGsqKhIDz/8sM466yy98847yszM1NNPP60dO3bUOa4xSyDy8/PrHAsAZkAYBoAg9uc//1lHjhzR448/rujoaD3xxBOyWq164IEH5HA4ao/r2LGjJGn37t0NvlbNvrS0tGatGQC8iTAMAEHqo48+0scff6xrrrlGgwYNkiS1b99e9913n7Zs2aJnnnmm9tiakWo1I9Z+zul0as2aNYqJiamdZgEAZkAYBoAgdPjwYT322GNq166dHnjggTr7brjhBp199tn65z//qdWrV0uSMjMzFRkZqRUrVtR5QEeN77//XmVlZRo+fHidMW8AEOgshmEY/i4CABD4Hn/8cb311luaOXOmxowZU2ffvffeq88++0wLFizgyjAAU+HKMACgUe644w7Fx8frhRdekNvtrt2+fv16ffbZZxo3bhxBGIDpEIYBAI2SmJioxx57TDt37tScOXMkSVVVVXrkkUfUunVr/f73v/dzhQBw+ljYBQBotJEjR+r222/X7Nmz1bt3b3344Yfav3+/5s6dq/j4eH+XBwCnjTXDAAAACFoskwAAAEDQIgwDAAAgaBGGAQAAELQIwwAAAAhahGEAAAAELcIwAAAAghZhGAAAAEGLMAwAAICg9f8Dgh3K5XXm9QYAAAAASUVORK5CYII=",
"text/plain": [
"
"
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"system.table.mpl(x=\"mx\", y=[\"E\"])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## `micromagneticdata` analysis\n",
"\n",
"Similar to all other drivers, we can use `micromagneticdata` package to analyse the data. We start by creationg the data object:"
]
},
{
"cell_type": "code",
"execution_count": 6,
"metadata": {},
"outputs": [],
"source": [
"import micromagneticdata as md\n",
"\n",
"data = md.Data(name=system.name)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can have a look at all drives we did so far:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"metadata": {
"tags": [
"nbval-ignore-output"
]
},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
"
\n",
"
\n",
"
drive_number
\n",
"
date
\n",
"
time
\n",
"
driver
\n",
"
t
\n",
"
n
\n",
"
n_threads
\n",
"
\n",
" \n",
" \n",
"
\n",
"
0
\n",
"
0
\n",
"
2023-01-16
\n",
"
17:35:54
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
1
\n",
"
1
\n",
"
2023-01-16
\n",
"
17:35:58
\n",
"
TimeDriver
\n",
"
2.000000e-09
\n",
"
200.0
\n",
"
4.0
\n",
"
\n",
"
\n",
"
2
\n",
"
2
\n",
"
2023-01-16
\n",
"
17:37:00
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
3
\n",
"
3
\n",
"
2023-01-16
\n",
"
17:37:04
\n",
"
TimeDriver
\n",
"
2.000000e-09
\n",
"
200.0
\n",
"
4.0
\n",
"
\n",
"
\n",
"
4
\n",
"
4
\n",
"
2023-01-16
\n",
"
17:37:28
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
5
\n",
"
5
\n",
"
2023-01-16
\n",
"
17:38:02
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
6
\n",
"
6
\n",
"
2023-01-16
\n",
"
17:38:06
\n",
"
TimeDriver
\n",
"
2.000000e-09
\n",
"
200.0
\n",
"
4.0
\n",
"
\n",
"
\n",
"
7
\n",
"
7
\n",
"
2023-10-10
\n",
"
16:55:09
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
8
\n",
"
8
\n",
"
2023-10-10
\n",
"
16:55:13
\n",
"
TimeDriver
\n",
"
2.000000e-09
\n",
"
200.0
\n",
"
4.0
\n",
"
\n",
"
\n",
"
9
\n",
"
9
\n",
"
2023-10-18
\n",
"
12:37:23
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
"
\n",
"
10
\n",
"
10
\n",
"
2023-10-18
\n",
"
12:39:38
\n",
"
MinDriver
\n",
"
NaN
\n",
"
NaN
\n",
"
NaN
\n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" drive_number date time driver t n \\\n",
"0 0 2023-01-16 17:35:54 MinDriver NaN NaN \n",
"1 1 2023-01-16 17:35:58 TimeDriver 2.000000e-09 200.0 \n",
"2 2 2023-01-16 17:37:00 MinDriver NaN NaN \n",
"3 3 2023-01-16 17:37:04 TimeDriver 2.000000e-09 200.0 \n",
"4 4 2023-01-16 17:37:28 MinDriver NaN NaN \n",
"5 5 2023-01-16 17:38:02 MinDriver NaN NaN \n",
"6 6 2023-01-16 17:38:06 TimeDriver 2.000000e-09 200.0 \n",
"7 7 2023-10-10 16:55:09 MinDriver NaN NaN \n",
"8 8 2023-10-10 16:55:13 TimeDriver 2.000000e-09 200.0 \n",
"9 9 2023-10-18 12:37:23 MinDriver NaN NaN \n",
"10 10 2023-10-18 12:39:38 MinDriver NaN NaN \n",
"\n",
" n_threads \n",
"0 NaN \n",
"1 4.0 \n",
"2 NaN \n",
"3 4.0 \n",
"4 NaN \n",
"5 NaN \n",
"6 4.0 \n",
"7 NaN \n",
"8 4.0 \n",
"9 NaN \n",
"10 NaN "
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data.info"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"There is only one drive and we can get it by passing `0` (ot `-1`) as an index:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [],
"source": [
"drive = data[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"We can now plot the magnetisation at individual iterations, by indexing it again with the step number and do all usual operations allowed by `discretisedfield.Field` object."
]
},
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"Field\n",
"
\n",
" \n",
"
Mesh\n",
"
\n",
"
Region\n",
"
\n",
"
pmin = [-5e-08, -5e-08, 0.0]
\n",
"
pmax = [5e-08, 5e-08, 1e-08]
\n",
"
dims = ['x', 'y', 'z']
\n",
"
units = ['m', 'm', 'm']
\n",
"
\n",
"
n = [20, 20, 2]
\n",
"
\n",
"
nvdim = 3
\n",
"
vdims:\n",
"
x
\n",
"
y
\n",
"
z
\n",
"
\n",
"
\n",
"
unit = A/m
\n",
"
"
],
"text/plain": [
"Field(Mesh(Region(pmin=[-5e-08, -5e-08, 0.0], pmax=[5e-08, 5e-08, 1e-08], dims=['x', 'y', 'z'], units=['m', 'm', 'm']), n=[20, 20, 2]), nvdim=3, vdims: (x, y, z), unit=A/m)"
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"drive[0]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"The number of steps in the drive is:"
]
},
{
"cell_type": "code",
"execution_count": 10,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"14"
]
},
"execution_count": 10,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"drive.n"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Let us now create an interactive plot. For details on how to create custom interactive plots, please have a look at other tutorials."
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {
"editable": true,
"slideshow": {
"slide_type": ""
},
"tags": [
"nbval-ignore-output"
]
},
"outputs": [
{
"data": {
"application/javascript": [
"(function(root) {\n",
" function now() {\n",
" return new Date();\n",
" }\n",
"\n",
" var force = true;\n",
" var py_version = '3.2.2'.replace('rc', '-rc.').replace('.dev', '-dev.');\n",
" var is_dev = py_version.indexOf(\"+\") !== -1 || py_version.indexOf(\"-\") !== -1;\n",
" var reloading = false;\n",
" var Bokeh = root.Bokeh;\n",
" var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n",
"\n",
" if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n",
" root._bokeh_timeout = Date.now() + 5000;\n",
" root._bokeh_failed_load = false;\n",
" }\n",
"\n",
" function run_callbacks() {\n",
" try {\n",
" root._bokeh_onload_callbacks.forEach(function(callback) {\n",
" if (callback != null)\n",
" callback();\n",
" });\n",
" } finally {\n",
" delete root._bokeh_onload_callbacks;\n",
" }\n",
" console.debug(\"Bokeh: all callbacks have finished\");\n",
" }\n",
"\n",
" function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n",
" if (css_urls == null) css_urls = [];\n",
" if (js_urls == null) js_urls = [];\n",
" if (js_modules == null) js_modules = [];\n",
" if (js_exports == null) js_exports = {};\n",
"\n",
" root._bokeh_onload_callbacks.push(callback);\n",
"\n",
" if (root._bokeh_is_loading > 0) {\n",
" console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n",
" return null;\n",
" }\n",
" if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n",
" run_callbacks();\n",
" return null;\n",
" }\n",
" if (!reloading) {\n",
" console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n",
" }\n",
"\n",
" function on_load() {\n",
" root._bokeh_is_loading--;\n",
" if (root._bokeh_is_loading === 0) {\n",
" console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n",
" run_callbacks()\n",
" }\n",
" }\n",
" window._bokeh_on_load = on_load\n",
"\n",
" function on_error() {\n",
" console.error(\"failed to load \" + url);\n",
" }\n",
"\n",
" var skip = [];\n",
" if (window.requirejs) {\n",
" window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n",
" require([\"jspanel\"], function(jsPanel) {\n",
"\twindow.jsPanel = jsPanel\n",
"\ton_load()\n",
" })\n",
" require([\"jspanel-modal\"], function() {\n",
"\ton_load()\n",
" })\n",
" require([\"jspanel-tooltip\"], function() {\n",
"\ton_load()\n",
" })\n",
" require([\"jspanel-hint\"], function() {\n",
"\ton_load()\n",
" })\n",
" require([\"jspanel-layout\"], function() {\n",
"\ton_load()\n",
" })\n",
" require([\"jspanel-contextmenu\"], function() {\n",
"\ton_load()\n",
" })\n",
" require([\"jspanel-dock\"], function() {\n",
"\ton_load()\n",
" })\n",
" require([\"gridstack\"], function(GridStack) {\n",
"\twindow.GridStack = GridStack\n",
"\ton_load()\n",
" })\n",
" require([\"notyf\"], function() {\n",
"\ton_load()\n",
" })\n",
" root._bokeh_is_loading = css_urls.length + 9;\n",
" } else {\n",
" root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n",
" }\n",
"\n",
" var existing_stylesheets = []\n",
" var links = document.getElementsByTagName('link')\n",
" for (var i = 0; i < links.length; i++) {\n",
" var link = links[i]\n",
" if (link.href != null) {\n",
"\texisting_stylesheets.push(link.href)\n",
" }\n",
" }\n",
" for (var i = 0; i < css_urls.length; i++) {\n",
" var url = css_urls[i];\n",
" if (existing_stylesheets.indexOf(url) !== -1) {\n",
"\ton_load()\n",
"\tcontinue;\n",
" }\n",
" const element = document.createElement(\"link\");\n",
" element.onload = on_load;\n",
" element.onerror = on_error;\n",
" element.rel = \"stylesheet\";\n",
" element.type = \"text/css\";\n",
" element.href = url;\n",
" console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n",
" document.body.appendChild(element);\n",
" } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n",
" var urls = ['https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n",
" for (var i = 0; i < urls.length; i++) {\n",
" skip.push(urls[i])\n",
" }\n",
" } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n",
" var urls = ['https://cdn.holoviz.org/panel/1.2.3/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n",
" for (var i = 0; i < urls.length; i++) {\n",
" skip.push(urls[i])\n",
" }\n",
" } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n",
" var urls = ['https://cdn.holoviz.org/panel/1.2.3/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n",
" for (var i = 0; i < urls.length; i++) {\n",
" skip.push(urls[i])\n",
" }\n",
" } var existing_scripts = []\n",
" var scripts = document.getElementsByTagName('script')\n",
" for (var i = 0; i < scripts.length; i++) {\n",
" var script = scripts[i]\n",
" if (script.src != null) {\n",
"\texisting_scripts.push(script.src)\n",
" }\n",
" }\n",
" for (var i = 0; i < js_urls.length; i++) {\n",
" var url = js_urls[i];\n",
" if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n",
"\tif (!window.requirejs) {\n",
"\t on_load();\n",
"\t}\n",
"\tcontinue;\n",
" }\n",
" var element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error;\n",
" element.async = false;\n",
" element.src = url;\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\n",
" }\n",
" for (var i = 0; i < js_modules.length; i++) {\n",
" var url = js_modules[i];\n",
" if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n",
"\tif (!window.requirejs) {\n",
"\t on_load();\n",
"\t}\n",
"\tcontinue;\n",
" }\n",
" var element = document.createElement('script');\n",
" element.onload = on_load;\n",
" element.onerror = on_error;\n",
" element.async = false;\n",
" element.src = url;\n",
" element.type = \"module\";\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" document.head.appendChild(element);\n",
" }\n",
" for (const name in js_exports) {\n",
" var url = js_exports[name];\n",
" if (skip.indexOf(url) >= 0 || root[name] != null) {\n",
"\tif (!window.requirejs) {\n",
"\t on_load();\n",
"\t}\n",
"\tcontinue;\n",
" }\n",
" var element = document.createElement('script');\n",
" element.onerror = on_error;\n",
" element.async = false;\n",
" element.type = \"module\";\n",
" console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n",
" element.textContent = `\n",
" import ${name} from \"${url}\"\n",
" window.${name} = ${name}\n",
" window._bokeh_on_load()\n",
" `\n",
" document.head.appendChild(element);\n",
" }\n",
" if (!js_urls.length && !js_modules.length) {\n",
" on_load()\n",
" }\n",
" };\n",
"\n",
" function inject_raw_css(css) {\n",
" const element = document.createElement(\"style\");\n",
" element.appendChild(document.createTextNode(css));\n",
" document.body.appendChild(element);\n",
" }\n",
"\n",
" var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.2.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.2.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.2.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.2.2.min.js\", \"https://cdn.holoviz.org/panel/1.2.3/dist/panel.min.js\"];\n",
" var js_modules = [];\n",
" var js_exports = {};\n",
" var css_urls = [];\n",
" var inline_js = [ function(Bokeh) {\n",
" Bokeh.set_log_level(\"info\");\n",
" },\n",
"function(Bokeh) {} // ensure no trailing comma for IE\n",
" ];\n",
"\n",
" function run_inline_js() {\n",
" if ((root.Bokeh !== undefined) || (force === true)) {\n",
" for (var i = 0; i < inline_js.length; i++) {\n",
" inline_js[i].call(root, root.Bokeh);\n",
" }\n",
" // Cache old bokeh versions\n",
" if (Bokeh != undefined && !reloading) {\n",
"\tvar NewBokeh = root.Bokeh;\n",
"\tif (Bokeh.versions === undefined) {\n",
"\t Bokeh.versions = new Map();\n",
"\t}\n",
"\tif (NewBokeh.version !== Bokeh.version) {\n",
"\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n",
"\t}\n",
"\troot.Bokeh = Bokeh;\n",
" }} else if (Date.now() < root._bokeh_timeout) {\n",
" setTimeout(run_inline_js, 100);\n",
" } else if (!root._bokeh_failed_load) {\n",
" console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n",
" root._bokeh_failed_load = true;\n",
" }\n",
" root._bokeh_is_initializing = false\n",
" }\n",
"\n",
" function load_or_wait() {\n",
" // Implement a backoff loop that tries to ensure we do not load multiple\n",
" // versions of Bokeh and its dependencies at the same time.\n",
" // In recent versions we use the root._bokeh_is_initializing flag\n",
" // to determine whether there is an ongoing attempt to initialize\n",
" // bokeh, however for backward compatibility we also try to ensure\n",
" // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n",
" // before older versions are fully initialized.\n",
" if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n",
" root._bokeh_is_initializing = false;\n",
" root._bokeh_onload_callbacks = undefined;\n",
" console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n",
" load_or_wait();\n",
" } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n",
" setTimeout(load_or_wait, 100);\n",
" } else {\n",
" Bokeh = root.Bokeh;\n",
" bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n",
" root._bokeh_is_initializing = true\n",
" root._bokeh_onload_callbacks = []\n",
" if (!reloading && (!bokeh_loaded || is_dev)) {\n",
"\troot.Bokeh = undefined;\n",
" }\n",
" load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n",
"\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n",
"\trun_inline_js();\n",
" });\n",
" }\n",
" }\n",
" // Give older versions of the autoload script a head-start to ensure\n",
" // they initialize before we start loading newer version.\n",
" setTimeout(load_or_wait, 100)\n",
"}(window));"
],
"application/vnd.holoviews_load.v0+json": "(function(root) {\n function now() {\n return new Date();\n }\n\n var force = true;\n var py_version = '3.2.2'.replace('rc', '-rc.').replace('.dev', '-dev.');\n var is_dev = py_version.indexOf(\"+\") !== -1 || py_version.indexOf(\"-\") !== -1;\n var reloading = false;\n var Bokeh = root.Bokeh;\n var bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n\n if (typeof (root._bokeh_timeout) === \"undefined\" || force) {\n root._bokeh_timeout = Date.now() + 5000;\n root._bokeh_failed_load = false;\n }\n\n function run_callbacks() {\n try {\n root._bokeh_onload_callbacks.forEach(function(callback) {\n if (callback != null)\n callback();\n });\n } finally {\n delete root._bokeh_onload_callbacks;\n }\n console.debug(\"Bokeh: all callbacks have finished\");\n }\n\n function load_libs(css_urls, js_urls, js_modules, js_exports, callback) {\n if (css_urls == null) css_urls = [];\n if (js_urls == null) js_urls = [];\n if (js_modules == null) js_modules = [];\n if (js_exports == null) js_exports = {};\n\n root._bokeh_onload_callbacks.push(callback);\n\n if (root._bokeh_is_loading > 0) {\n console.debug(\"Bokeh: BokehJS is being loaded, scheduling callback at\", now());\n return null;\n }\n if (js_urls.length === 0 && js_modules.length === 0 && Object.keys(js_exports).length === 0) {\n run_callbacks();\n return null;\n }\n if (!reloading) {\n console.debug(\"Bokeh: BokehJS not loaded, scheduling load and callback at\", now());\n }\n\n function on_load() {\n root._bokeh_is_loading--;\n if (root._bokeh_is_loading === 0) {\n console.debug(\"Bokeh: all BokehJS libraries/stylesheets loaded\");\n run_callbacks()\n }\n }\n window._bokeh_on_load = on_load\n\n function on_error() {\n console.error(\"failed to load \" + url);\n }\n\n var skip = [];\n if (window.requirejs) {\n window.requirejs.config({'packages': {}, 'paths': {'jspanel': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/jspanel', 'jspanel-modal': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal', 'jspanel-tooltip': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip', 'jspanel-hint': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint', 'jspanel-layout': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout', 'jspanel-contextmenu': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu', 'jspanel-dock': 'https://cdn.jsdelivr.net/npm/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock', 'gridstack': 'https://cdn.jsdelivr.net/npm/gridstack@7.2.3/dist/gridstack-all', 'notyf': 'https://cdn.jsdelivr.net/npm/notyf@3/notyf.min'}, 'shim': {'jspanel': {'exports': 'jsPanel'}, 'gridstack': {'exports': 'GridStack'}}});\n require([\"jspanel\"], function(jsPanel) {\n\twindow.jsPanel = jsPanel\n\ton_load()\n })\n require([\"jspanel-modal\"], function() {\n\ton_load()\n })\n require([\"jspanel-tooltip\"], function() {\n\ton_load()\n })\n require([\"jspanel-hint\"], function() {\n\ton_load()\n })\n require([\"jspanel-layout\"], function() {\n\ton_load()\n })\n require([\"jspanel-contextmenu\"], function() {\n\ton_load()\n })\n require([\"jspanel-dock\"], function() {\n\ton_load()\n })\n require([\"gridstack\"], function(GridStack) {\n\twindow.GridStack = GridStack\n\ton_load()\n })\n require([\"notyf\"], function() {\n\ton_load()\n })\n root._bokeh_is_loading = css_urls.length + 9;\n } else {\n root._bokeh_is_loading = css_urls.length + js_urls.length + js_modules.length + Object.keys(js_exports).length;\n }\n\n var existing_stylesheets = []\n var links = document.getElementsByTagName('link')\n for (var i = 0; i < links.length; i++) {\n var link = links[i]\n if (link.href != null) {\n\texisting_stylesheets.push(link.href)\n }\n }\n for (var i = 0; i < css_urls.length; i++) {\n var url = css_urls[i];\n if (existing_stylesheets.indexOf(url) !== -1) {\n\ton_load()\n\tcontinue;\n }\n const element = document.createElement(\"link\");\n element.onload = on_load;\n element.onerror = on_error;\n element.rel = \"stylesheet\";\n element.type = \"text/css\";\n element.href = url;\n console.debug(\"Bokeh: injecting link tag for BokehJS stylesheet: \", url);\n document.body.appendChild(element);\n } if (((window['jsPanel'] !== undefined) && (!(window['jsPanel'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/jspanel.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/modal/jspanel.modal.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/tooltip/jspanel.tooltip.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/hint/jspanel.hint.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/layout/jspanel.layout.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/contextmenu/jspanel.contextmenu.js', 'https://cdn.holoviz.org/panel/1.2.3/dist/bundled/floatpanel/jspanel4@4.12.0/dist/extensions/dock/jspanel.dock.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['GridStack'] !== undefined) && (!(window['GridStack'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.3/dist/bundled/gridstack/gridstack@7.2.3/dist/gridstack-all.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } if (((window['Notyf'] !== undefined) && (!(window['Notyf'] instanceof HTMLElement))) || window.requirejs) {\n var urls = ['https://cdn.holoviz.org/panel/1.2.3/dist/bundled/notificationarea/notyf@3/notyf.min.js'];\n for (var i = 0; i < urls.length; i++) {\n skip.push(urls[i])\n }\n } var existing_scripts = []\n var scripts = document.getElementsByTagName('script')\n for (var i = 0; i < scripts.length; i++) {\n var script = scripts[i]\n if (script.src != null) {\n\texisting_scripts.push(script.src)\n }\n }\n for (var i = 0; i < js_urls.length; i++) {\n var url = js_urls[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (var i = 0; i < js_modules.length; i++) {\n var url = js_modules[i];\n if (skip.indexOf(url) !== -1 || existing_scripts.indexOf(url) !== -1) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onload = on_load;\n element.onerror = on_error;\n element.async = false;\n element.src = url;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n document.head.appendChild(element);\n }\n for (const name in js_exports) {\n var url = js_exports[name];\n if (skip.indexOf(url) >= 0 || root[name] != null) {\n\tif (!window.requirejs) {\n\t on_load();\n\t}\n\tcontinue;\n }\n var element = document.createElement('script');\n element.onerror = on_error;\n element.async = false;\n element.type = \"module\";\n console.debug(\"Bokeh: injecting script tag for BokehJS library: \", url);\n element.textContent = `\n import ${name} from \"${url}\"\n window.${name} = ${name}\n window._bokeh_on_load()\n `\n document.head.appendChild(element);\n }\n if (!js_urls.length && !js_modules.length) {\n on_load()\n }\n };\n\n function inject_raw_css(css) {\n const element = document.createElement(\"style\");\n element.appendChild(document.createTextNode(css));\n document.body.appendChild(element);\n }\n\n var js_urls = [\"https://cdn.bokeh.org/bokeh/release/bokeh-3.2.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-gl-3.2.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-widgets-3.2.2.min.js\", \"https://cdn.bokeh.org/bokeh/release/bokeh-tables-3.2.2.min.js\", \"https://cdn.holoviz.org/panel/1.2.3/dist/panel.min.js\"];\n var js_modules = [];\n var js_exports = {};\n var css_urls = [];\n var inline_js = [ function(Bokeh) {\n Bokeh.set_log_level(\"info\");\n },\nfunction(Bokeh) {} // ensure no trailing comma for IE\n ];\n\n function run_inline_js() {\n if ((root.Bokeh !== undefined) || (force === true)) {\n for (var i = 0; i < inline_js.length; i++) {\n inline_js[i].call(root, root.Bokeh);\n }\n // Cache old bokeh versions\n if (Bokeh != undefined && !reloading) {\n\tvar NewBokeh = root.Bokeh;\n\tif (Bokeh.versions === undefined) {\n\t Bokeh.versions = new Map();\n\t}\n\tif (NewBokeh.version !== Bokeh.version) {\n\t Bokeh.versions.set(NewBokeh.version, NewBokeh)\n\t}\n\troot.Bokeh = Bokeh;\n }} else if (Date.now() < root._bokeh_timeout) {\n setTimeout(run_inline_js, 100);\n } else if (!root._bokeh_failed_load) {\n console.log(\"Bokeh: BokehJS failed to load within specified timeout.\");\n root._bokeh_failed_load = true;\n }\n root._bokeh_is_initializing = false\n }\n\n function load_or_wait() {\n // Implement a backoff loop that tries to ensure we do not load multiple\n // versions of Bokeh and its dependencies at the same time.\n // In recent versions we use the root._bokeh_is_initializing flag\n // to determine whether there is an ongoing attempt to initialize\n // bokeh, however for backward compatibility we also try to ensure\n // that we do not start loading a newer (Panel>=1.0 and Bokeh>3) version\n // before older versions are fully initialized.\n if (root._bokeh_is_initializing && Date.now() > root._bokeh_timeout) {\n root._bokeh_is_initializing = false;\n root._bokeh_onload_callbacks = undefined;\n console.log(\"Bokeh: BokehJS was loaded multiple times but one version failed to initialize.\");\n load_or_wait();\n } else if (root._bokeh_is_initializing || (typeof root._bokeh_is_initializing === \"undefined\" && root._bokeh_onload_callbacks !== undefined)) {\n setTimeout(load_or_wait, 100);\n } else {\n Bokeh = root.Bokeh;\n bokeh_loaded = Bokeh != null && (Bokeh.version === py_version || (Bokeh.versions !== undefined && Bokeh.versions.has(py_version)));\n root._bokeh_is_initializing = true\n root._bokeh_onload_callbacks = []\n if (!reloading && (!bokeh_loaded || is_dev)) {\n\troot.Bokeh = undefined;\n }\n load_libs(css_urls, js_urls, js_modules, js_exports, function() {\n\tconsole.debug(\"Bokeh: BokehJS plotting callback run at\", now());\n\trun_inline_js();\n });\n }\n }\n // Give older versions of the autoload script a head-start to ensure\n // they initialize before we start loading newer version.\n setTimeout(load_or_wait, 100)\n}(window));"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/javascript": [
"\n",
"if ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n",
" window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n",
"}\n",
"\n",
"\n",
" function JupyterCommManager() {\n",
" }\n",
"\n",
" JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n",
" if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n",
" var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n",
" comm_manager.register_target(comm_id, function(comm) {\n",
" comm.on_msg(msg_handler);\n",
" });\n",
" } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n",
" window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n",
" comm.onMsg = msg_handler;\n",
" });\n",
" } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n",
" google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n",
" var messages = comm.messages[Symbol.asyncIterator]();\n",
" function processIteratorResult(result) {\n",
" var message = result.value;\n",
" console.log(message)\n",
" var content = {data: message.data, comm_id};\n",
" var buffers = []\n",
" for (var buffer of message.buffers || []) {\n",
" buffers.push(new DataView(buffer))\n",
" }\n",
" var metadata = message.metadata || {};\n",
" var msg = {content, buffers, metadata}\n",
" msg_handler(msg);\n",
" return messages.next().then(processIteratorResult);\n",
" }\n",
" return messages.next().then(processIteratorResult);\n",
" })\n",
" }\n",
" }\n",
"\n",
" JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n",
" if (comm_id in window.PyViz.comms) {\n",
" return window.PyViz.comms[comm_id];\n",
" } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n",
" var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n",
" var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n",
" if (msg_handler) {\n",
" comm.on_msg(msg_handler);\n",
" }\n",
" } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n",
" var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n",
" comm.open();\n",
" if (msg_handler) {\n",
" comm.onMsg = msg_handler;\n",
" }\n",
" } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n",
" var comm_promise = google.colab.kernel.comms.open(comm_id)\n",
" comm_promise.then((comm) => {\n",
" window.PyViz.comms[comm_id] = comm;\n",
" if (msg_handler) {\n",
" var messages = comm.messages[Symbol.asyncIterator]();\n",
" function processIteratorResult(result) {\n",
" var message = result.value;\n",
" var content = {data: message.data};\n",
" var metadata = message.metadata || {comm_id};\n",
" var msg = {content, metadata}\n",
" msg_handler(msg);\n",
" return messages.next().then(processIteratorResult);\n",
" }\n",
" return messages.next().then(processIteratorResult);\n",
" }\n",
" }) \n",
" var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n",
" return comm_promise.then((comm) => {\n",
" comm.send(data, metadata, buffers, disposeOnDone);\n",
" });\n",
" };\n",
" var comm = {\n",
" send: sendClosure\n",
" };\n",
" }\n",
" window.PyViz.comms[comm_id] = comm;\n",
" return comm;\n",
" }\n",
" window.PyViz.comm_manager = new JupyterCommManager();\n",
" \n",
"\n",
"\n",
"var JS_MIME_TYPE = 'application/javascript';\n",
"var HTML_MIME_TYPE = 'text/html';\n",
"var EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\n",
"var CLASS_NAME = 'output';\n",
"\n",
"/**\n",
" * Render data to the DOM node\n",
" */\n",
"function render(props, node) {\n",
" var div = document.createElement(\"div\");\n",
" var script = document.createElement(\"script\");\n",
" node.appendChild(div);\n",
" node.appendChild(script);\n",
"}\n",
"\n",
"/**\n",
" * Handle when a new output is added\n",
" */\n",
"function handle_add_output(event, handle) {\n",
" var output_area = handle.output_area;\n",
" var output = handle.output;\n",
" if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n",
" return\n",
" }\n",
" var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n",
" var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n",
" if (id !== undefined) {\n",
" var nchildren = toinsert.length;\n",
" var html_node = toinsert[nchildren-1].children[0];\n",
" html_node.innerHTML = output.data[HTML_MIME_TYPE];\n",
" var scripts = [];\n",
" var nodelist = html_node.querySelectorAll(\"script\");\n",
" for (var i in nodelist) {\n",
" if (nodelist.hasOwnProperty(i)) {\n",
" scripts.push(nodelist[i])\n",
" }\n",
" }\n",
"\n",
" scripts.forEach( function (oldScript) {\n",
" var newScript = document.createElement(\"script\");\n",
" var attrs = [];\n",
" var nodemap = oldScript.attributes;\n",
" for (var j in nodemap) {\n",
" if (nodemap.hasOwnProperty(j)) {\n",
" attrs.push(nodemap[j])\n",
" }\n",
" }\n",
" attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n",
" newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n",
" oldScript.parentNode.replaceChild(newScript, oldScript);\n",
" });\n",
" if (JS_MIME_TYPE in output.data) {\n",
" toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n",
" }\n",
" output_area._hv_plot_id = id;\n",
" if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n",
" window.PyViz.plot_index[id] = Bokeh.index[id];\n",
" } else {\n",
" window.PyViz.plot_index[id] = null;\n",
" }\n",
" } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n",
" var bk_div = document.createElement(\"div\");\n",
" bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n",
" var script_attrs = bk_div.children[0].attributes;\n",
" for (var i = 0; i < script_attrs.length; i++) {\n",
" toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n",
" }\n",
" // store reference to server id on output_area\n",
" output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n",
" }\n",
"}\n",
"\n",
"/**\n",
" * Handle when an output is cleared or removed\n",
" */\n",
"function handle_clear_output(event, handle) {\n",
" var id = handle.cell.output_area._hv_plot_id;\n",
" var server_id = handle.cell.output_area._bokeh_server_id;\n",
" if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n",
" var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n",
" if (server_id !== null) {\n",
" comm.send({event_type: 'server_delete', 'id': server_id});\n",
" return;\n",
" } else if (comm !== null) {\n",
" comm.send({event_type: 'delete', 'id': id});\n",
" }\n",
" delete PyViz.plot_index[id];\n",
" if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n",
" var doc = window.Bokeh.index[id].model.document\n",
" doc.clear();\n",
" const i = window.Bokeh.documents.indexOf(doc);\n",
" if (i > -1) {\n",
" window.Bokeh.documents.splice(i, 1);\n",
" }\n",
" }\n",
"}\n",
"\n",
"/**\n",
" * Handle kernel restart event\n",
" */\n",
"function handle_kernel_cleanup(event, handle) {\n",
" delete PyViz.comms[\"hv-extension-comm\"];\n",
" window.PyViz.plot_index = {}\n",
"}\n",
"\n",
"/**\n",
" * Handle update_display_data messages\n",
" */\n",
"function handle_update_output(event, handle) {\n",
" handle_clear_output(event, {cell: {output_area: handle.output_area}})\n",
" handle_add_output(event, handle)\n",
"}\n",
"\n",
"function register_renderer(events, OutputArea) {\n",
" function append_mime(data, metadata, element) {\n",
" // create a DOM node to render to\n",
" var toinsert = this.create_output_subarea(\n",
" metadata,\n",
" CLASS_NAME,\n",
" EXEC_MIME_TYPE\n",
" );\n",
" this.keyboard_manager.register_events(toinsert);\n",
" // Render to node\n",
" var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n",
" render(props, toinsert[0]);\n",
" element.append(toinsert);\n",
" return toinsert\n",
" }\n",
"\n",
" events.on('output_added.OutputArea', handle_add_output);\n",
" events.on('output_updated.OutputArea', handle_update_output);\n",
" events.on('clear_output.CodeCell', handle_clear_output);\n",
" events.on('delete.Cell', handle_clear_output);\n",
" events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n",
"\n",
" OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n",
" safe: true,\n",
" index: 0\n",
" });\n",
"}\n",
"\n",
"if (window.Jupyter !== undefined) {\n",
" try {\n",
" var events = require('base/js/events');\n",
" var OutputArea = require('notebook/js/outputarea').OutputArea;\n",
" if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n",
" register_renderer(events, OutputArea);\n",
" }\n",
" } catch(err) {\n",
" }\n",
"}\n"
],
"application/vnd.holoviews_load.v0+json": "\nif ((window.PyViz === undefined) || (window.PyViz instanceof HTMLElement)) {\n window.PyViz = {comms: {}, comm_status:{}, kernels:{}, receivers: {}, plot_index: []}\n}\n\n\n function JupyterCommManager() {\n }\n\n JupyterCommManager.prototype.register_target = function(plot_id, comm_id, msg_handler) {\n if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n comm_manager.register_target(comm_id, function(comm) {\n comm.on_msg(msg_handler);\n });\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n window.PyViz.kernels[plot_id].registerCommTarget(comm_id, function(comm) {\n comm.onMsg = msg_handler;\n });\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n google.colab.kernel.comms.registerTarget(comm_id, (comm) => {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n console.log(message)\n var content = {data: message.data, comm_id};\n var buffers = []\n for (var buffer of message.buffers || []) {\n buffers.push(new DataView(buffer))\n }\n var metadata = message.metadata || {};\n var msg = {content, buffers, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n })\n }\n }\n\n JupyterCommManager.prototype.get_client_comm = function(plot_id, comm_id, msg_handler) {\n if (comm_id in window.PyViz.comms) {\n return window.PyViz.comms[comm_id];\n } else if (window.comm_manager || ((window.Jupyter !== undefined) && (Jupyter.notebook.kernel != null))) {\n var comm_manager = window.comm_manager || Jupyter.notebook.kernel.comm_manager;\n var comm = comm_manager.new_comm(comm_id, {}, {}, {}, comm_id);\n if (msg_handler) {\n comm.on_msg(msg_handler);\n }\n } else if ((plot_id in window.PyViz.kernels) && (window.PyViz.kernels[plot_id])) {\n var comm = window.PyViz.kernels[plot_id].connectToComm(comm_id);\n comm.open();\n if (msg_handler) {\n comm.onMsg = msg_handler;\n }\n } else if (typeof google != 'undefined' && google.colab.kernel != null) {\n var comm_promise = google.colab.kernel.comms.open(comm_id)\n comm_promise.then((comm) => {\n window.PyViz.comms[comm_id] = comm;\n if (msg_handler) {\n var messages = comm.messages[Symbol.asyncIterator]();\n function processIteratorResult(result) {\n var message = result.value;\n var content = {data: message.data};\n var metadata = message.metadata || {comm_id};\n var msg = {content, metadata}\n msg_handler(msg);\n return messages.next().then(processIteratorResult);\n }\n return messages.next().then(processIteratorResult);\n }\n }) \n var sendClosure = (data, metadata, buffers, disposeOnDone) => {\n return comm_promise.then((comm) => {\n comm.send(data, metadata, buffers, disposeOnDone);\n });\n };\n var comm = {\n send: sendClosure\n };\n }\n window.PyViz.comms[comm_id] = comm;\n return comm;\n }\n window.PyViz.comm_manager = new JupyterCommManager();\n \n\n\nvar JS_MIME_TYPE = 'application/javascript';\nvar HTML_MIME_TYPE = 'text/html';\nvar EXEC_MIME_TYPE = 'application/vnd.holoviews_exec.v0+json';\nvar CLASS_NAME = 'output';\n\n/**\n * Render data to the DOM node\n */\nfunction render(props, node) {\n var div = document.createElement(\"div\");\n var script = document.createElement(\"script\");\n node.appendChild(div);\n node.appendChild(script);\n}\n\n/**\n * Handle when a new output is added\n */\nfunction handle_add_output(event, handle) {\n var output_area = handle.output_area;\n var output = handle.output;\n if ((output.data == undefined) || (!output.data.hasOwnProperty(EXEC_MIME_TYPE))) {\n return\n }\n var id = output.metadata[EXEC_MIME_TYPE][\"id\"];\n var toinsert = output_area.element.find(\".\" + CLASS_NAME.split(' ')[0]);\n if (id !== undefined) {\n var nchildren = toinsert.length;\n var html_node = toinsert[nchildren-1].children[0];\n html_node.innerHTML = output.data[HTML_MIME_TYPE];\n var scripts = [];\n var nodelist = html_node.querySelectorAll(\"script\");\n for (var i in nodelist) {\n if (nodelist.hasOwnProperty(i)) {\n scripts.push(nodelist[i])\n }\n }\n\n scripts.forEach( function (oldScript) {\n var newScript = document.createElement(\"script\");\n var attrs = [];\n var nodemap = oldScript.attributes;\n for (var j in nodemap) {\n if (nodemap.hasOwnProperty(j)) {\n attrs.push(nodemap[j])\n }\n }\n attrs.forEach(function(attr) { newScript.setAttribute(attr.name, attr.value) });\n newScript.appendChild(document.createTextNode(oldScript.innerHTML));\n oldScript.parentNode.replaceChild(newScript, oldScript);\n });\n if (JS_MIME_TYPE in output.data) {\n toinsert[nchildren-1].children[1].textContent = output.data[JS_MIME_TYPE];\n }\n output_area._hv_plot_id = id;\n if ((window.Bokeh !== undefined) && (id in Bokeh.index)) {\n window.PyViz.plot_index[id] = Bokeh.index[id];\n } else {\n window.PyViz.plot_index[id] = null;\n }\n } else if (output.metadata[EXEC_MIME_TYPE][\"server_id\"] !== undefined) {\n var bk_div = document.createElement(\"div\");\n bk_div.innerHTML = output.data[HTML_MIME_TYPE];\n var script_attrs = bk_div.children[0].attributes;\n for (var i = 0; i < script_attrs.length; i++) {\n toinsert[toinsert.length - 1].childNodes[1].setAttribute(script_attrs[i].name, script_attrs[i].value);\n }\n // store reference to server id on output_area\n output_area._bokeh_server_id = output.metadata[EXEC_MIME_TYPE][\"server_id\"];\n }\n}\n\n/**\n * Handle when an output is cleared or removed\n */\nfunction handle_clear_output(event, handle) {\n var id = handle.cell.output_area._hv_plot_id;\n var server_id = handle.cell.output_area._bokeh_server_id;\n if (((id === undefined) || !(id in PyViz.plot_index)) && (server_id !== undefined)) { return; }\n var comm = window.PyViz.comm_manager.get_client_comm(\"hv-extension-comm\", \"hv-extension-comm\", function () {});\n if (server_id !== null) {\n comm.send({event_type: 'server_delete', 'id': server_id});\n return;\n } else if (comm !== null) {\n comm.send({event_type: 'delete', 'id': id});\n }\n delete PyViz.plot_index[id];\n if ((window.Bokeh !== undefined) & (id in window.Bokeh.index)) {\n var doc = window.Bokeh.index[id].model.document\n doc.clear();\n const i = window.Bokeh.documents.indexOf(doc);\n if (i > -1) {\n window.Bokeh.documents.splice(i, 1);\n }\n }\n}\n\n/**\n * Handle kernel restart event\n */\nfunction handle_kernel_cleanup(event, handle) {\n delete PyViz.comms[\"hv-extension-comm\"];\n window.PyViz.plot_index = {}\n}\n\n/**\n * Handle update_display_data messages\n */\nfunction handle_update_output(event, handle) {\n handle_clear_output(event, {cell: {output_area: handle.output_area}})\n handle_add_output(event, handle)\n}\n\nfunction register_renderer(events, OutputArea) {\n function append_mime(data, metadata, element) {\n // create a DOM node to render to\n var toinsert = this.create_output_subarea(\n metadata,\n CLASS_NAME,\n EXEC_MIME_TYPE\n );\n this.keyboard_manager.register_events(toinsert);\n // Render to node\n var props = {data: data, metadata: metadata[EXEC_MIME_TYPE]};\n render(props, toinsert[0]);\n element.append(toinsert);\n return toinsert\n }\n\n events.on('output_added.OutputArea', handle_add_output);\n events.on('output_updated.OutputArea', handle_update_output);\n events.on('clear_output.CodeCell', handle_clear_output);\n events.on('delete.Cell', handle_clear_output);\n events.on('kernel_ready.Kernel', handle_kernel_cleanup);\n\n OutputArea.prototype.register_mime_type(EXEC_MIME_TYPE, append_mime, {\n safe: true,\n index: 0\n });\n}\n\nif (window.Jupyter !== undefined) {\n try {\n var events = require('base/js/events');\n var OutputArea = require('notebook/js/outputarea').OutputArea;\n if (OutputArea.prototype.mime_types().indexOf(EXEC_MIME_TYPE) == -1) {\n register_renderer(events, OutputArea);\n }\n } catch(err) {\n }\n}\n"
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"text/html": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"application/vnd.holoviews_exec.v0+json": "",
"text/html": [
"