{
"cells": [
{
"cell_type": "markdown",
"id": "f9443025",
"metadata": {},
"source": [
"## Plotting\n",
"\n",
"This notebook demonstrates the plotting features of **OptiWindNet**."
]
},
{
"cell_type": "code",
"execution_count": 1,
"id": "f1fc8d4f",
"metadata": {},
"outputs": [],
"source": [
"from optiwindnet.importer import load_repository\n",
"from optiwindnet.interarraylib import G_from_S, assign_cables\n",
"from optiwindnet.mesh import make_planar_embedding\n",
"from optiwindnet.pathfinding import PathFinder\n",
"from optiwindnet.heuristics import constructor\n",
"import networkx as nx"
]
},
{
"cell_type": "markdown",
"id": "c385062c",
"metadata": {},
"source": [
"### Create a sample network"
]
},
{
"cell_type": "code",
"execution_count": 2,
"id": "4a8248d5",
"metadata": {},
"outputs": [],
"source": [
"locations = load_repository()\n",
"L = locations.london\n",
"P, A = make_planar_embedding(L)\n",
"S = constructor(A, capacity=7)\n",
"Gʹ = G_from_S(S, A)\n",
"G = PathFinder(Gʹ, planar=P, A=A).create_detours()"
]
},
{
"cell_type": "markdown",
"id": "22fed99c",
"metadata": {},
"source": [
"### Using SVG-based `svgplot()`\n",
"\n",
"The primary SVG-based plotting functions in OptiWindNet are `svgplot()` and `svgpplot()`. They produce extremely clean, lightweight, and modern SVG figures natively suitable for web and Jupyter notebook displays, keeping the `.ipynb` files small and search-friendly."
]
},
{
"cell_type": "code",
"execution_count": 3,
"id": "f7f4877e",
"metadata": {},
"outputs": [],
"source": [
"from optiwindnet.svg import svgplot, svgpplot"
]
},
{
"cell_type": "code",
"execution_count": 4,
"id": "42c45aab",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 4,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G)"
]
},
{
"cell_type": "markdown",
"id": "7b1dbaeb",
"metadata": {},
"source": [
"If `G` is assigned cable types, it is encoded in the thickness of the edges (higher capacities represented by thicker lines). The total network cost is also added to the infobox."
]
},
{
"cell_type": "code",
"execution_count": 5,
"id": "3c7db613",
"metadata": {},
"outputs": [],
"source": [
"# one 2-tuple for each cable type: (capacity, linear cost)\n",
"# capacities must be increasing\n",
"assign_cables(G, cables=[(2, 400), (4, 600), (7, 900)])"
]
},
{
"cell_type": "code",
"execution_count": 6,
"id": "e2d77a9a",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 6,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G)"
]
},
{
"cell_type": "markdown",
"id": "7755e422",
"metadata": {},
"source": [
"#### Node tags and figure legends\n",
"\n",
"`svgplot()` supports a variety of node tagging options and automatic legend strip generation. Use the `node_tag` argument to select what information is rendered inside the nodes:"
]
},
{
"cell_type": "code",
"execution_count": 7,
"id": "7b728f5f",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 7,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G, node_tag='label', infobox=False, legend=True)"
]
},
{
"cell_type": "markdown",
"id": "94fc9b92",
"metadata": {},
"source": [
"Alternatively, the internal index of the nodes can be shown instead of their labels by setting `node_tag=True`:"
]
},
{
"cell_type": "code",
"execution_count": 8,
"id": "ff435b73",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G, node_tag=True, infobox=False)"
]
},
{
"cell_type": "markdown",
"id": "2219051c",
"metadata": {},
"source": [
"The nodes can also be tagged by the power flow (load) they export towards the substation:"
]
},
{
"cell_type": "code",
"execution_count": 9,
"id": "574112e7",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 9,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G, node_tag='load')"
]
},
{
"cell_type": "markdown",
"id": "365e0f2e",
"metadata": {},
"source": [
"#### Displaying in loops and saving to files\n",
"\n",
"The `svgplot()` function does not create an inline image immediately upon being called; the SVG is displayed when the object returned by the call is the cell output. To display figures created within code loops, use `IPython.display.display`."
]
},
{
"cell_type": "code",
"execution_count": 10,
"id": "38b55a55",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
},
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"for cap in [9, 7, 5]:\n",
" S_loop = constructor(A, capacity=cap)\n",
" G_loopʹ = G_from_S(S_loop, A)\n",
" G_loop = PathFinder(G_loopʹ, planar=P, A=A).create_detours()\n",
" display(svgplot(G_loop))"
]
},
{
"cell_type": "markdown",
"id": "197c2ab2",
"metadata": {},
"source": [
"To save an SVG representation to a file:\n",
"```python\n",
"svgplot(G).save('myfig.svg')\n",
"```"
]
},
{
"cell_type": "markdown",
"id": "06cccc18",
"metadata": {},
"source": [
"### Dark and Light plotting themes\n",
"\n",
"`svgplot()` automatically tries to match the operating system's theme via the `darkdetect` package. If you prefer to enforce a theme programmatically, set the `dark` parameter to `True` or `False`:"
]
},
{
"cell_type": "code",
"execution_count": 11,
"id": "038bec3e",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 11,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G, dark=False)"
]
},
{
"cell_type": "markdown",
"id": "374fcdda",
"metadata": {},
"source": [
"### Rotated locations\n",
"\n",
"Each location included in OptiWindNet has a graph attribute called `landscape_angle`. This represents the rotation needed to orient the wind farm best on a landscape screen. If you prefer to orient the plot with North always up, set `landscape=False`:"
]
},
{
"cell_type": "code",
"execution_count": 12,
"id": "db6f7a1d",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
""
],
"text/plain": [
""
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"svgplot(G, landscape=False)"
]
},
{
"cell_type": "markdown",
"id": "571e9522",
"metadata": {},
"source": [
"### Using Matplotlib-based `gplot()` & `pplot()`\n",
"\n",
"OptiWindNet also provides Matplotlib-based plotting functions, `gplot()` and `pplot()`, under `optiwindnet.plotting`.\n",
"\n",
"While SVG-based plots are recommended for direct notebook displays, the Matplotlib-based functions are essential when you want to take advantage of Matplotlib-specific capabilities, such as multi-axis plotting and advanced custom layout integrations."
]
},
{
"cell_type": "code",
"execution_count": 13,
"id": "d033af5a",
"metadata": {},
"outputs": [],
"source": [
"import matplotlib.pyplot as plt\n",
"%config InlineBackend.figure_formats = ['svg']\n",
"plt.rcParams['svg.fonttype'] = 'none'\n",
"from optiwindnet.plotting import gplot, pplot"
]
},
{
"cell_type": "markdown",
"id": "fa6b99b9",
"metadata": {},
"source": [
"#### 1. Custom Multi-Axis Subplots\n",
"\n",
"You can pass a pre-existing `plt.Axes` object to place plots side-by-side or integrate them inside more complex subplots:"
]
},
{
"cell_type": "code",
"execution_count": 14,
"id": "781fcd61",
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
""
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
},
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"fig, (ax1, ax2) = plt.subplots(1, 2, facecolor='none', figsize=(9, 3))\n",
"pplot(P, A, ax=ax1)\n",
"gplot(A, ax=ax2)"
]
},
{
"cell_type": "markdown",
"id": "754552cf",
"metadata": {},
"source": [
"`pplot(P, A)` is useful for visualizing the pathfinding triangulation mesh and available edges graph `A` for debugging geometry."
]
},
{
"cell_type": "markdown",
"id": "6d8a6e8f",
"metadata": {},
"source": [
"#### 2. Matplotlib Axes Customization and Saving\n",
"\n",
"`gplot()` returns a standard `plt.Axes` object. You can use it to adjust any aspect of the figure or to save it directly using Matplotlib backends (such as exporting to PDF, PNG, or EPS formats):"
]
},
{
"cell_type": "code",
"execution_count": 15,
"id": "ce405511",
"metadata": {},
"outputs": [
{
"data": {
"image/svg+xml": [
"\n",
"\n",
"\n"
],
"text/plain": [
""
]
},
"metadata": {},
"output_type": "display_data"
}
],
"source": [
"ax = gplot(G)\n",
"# ax.figure.savefig('myfig.pdf')"
]
}
],
"metadata": {
"language_info": {
"name": "python"
}
},
"nbformat": 4,
"nbformat_minor": 5
}