{ "cells": [ { "cell_type": "markdown", "id": "a2d556ea-37b0-47c5-a199-2cbfc68c95a9", "metadata": {}, "source": [ "# 4) Creating publication-ready game images" ] }, { "cell_type": "code", "execution_count": null, "id": "338dd237-2280-453c-a687-d65b9f9a56b6", "metadata": {}, "outputs": [], "source": [ "from draw_tree import draw_tree\n", "\n", "import pygambit as gbt" ] }, { "cell_type": "markdown", "id": "53808931-cdc1-4b39-9a62-8c5166077a84", "metadata": {}, "source": [ "Using a combination of `pygambit` and the Gambit project's LaTeX graphics package `draw_tree`, we can generate publication quality images for games with just a few lines of code.\n", "\n", "This tutorial will demonstrate the key functionality of `draw_tree` when used for games built with `pygambit`, using an example game derived from the Gambit catalog.\n", "First, let's load the game:" ] }, { "cell_type": "code", "execution_count": null, "id": "7f1dfa89-84fb-45cd-ab99-0a8ed44c17bc", "metadata": {}, "outputs": [], "source": [ "g = gbt.catalog.load(\"2smp\")" ] }, { "cell_type": "markdown", "id": "f4141e1a-9728-4186-b547-d37050a63e66", "metadata": {}, "source": [ "Now let's see how `draw_tree` renders it with default settings:" ] }, { "cell_type": "code", "execution_count": null, "id": "e76fc30e-c03c-4fc6-ada1-733500609ca0", "metadata": {}, "outputs": [], "source": [ "draw_tree(g)" ] }, { "cell_type": "markdown", "id": "76363e9d-94df-430a-8ca9-c16b95f3880a", "metadata": {}, "source": [ "Already this looks good, but perhaps it would look neater if the terminal nodes were all extended to the bottom of the image for consistency.\n", "To achieve this, set `shared_terminal_depth=True`:" ] }, { "cell_type": "code", "execution_count": null, "id": "c9d4639a-8dc6-42c5-99a0-0a831117b551", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True\n", ")" ] }, { "cell_type": "markdown", "id": "e6f72192-1ba3-4252-9a4c-40c37df98ef0", "metadata": {}, "source": [ "This image is quite large, but the game isn't overly complex, so we can reduce the size with the `scale_factor`:" ] }, { "cell_type": "code", "execution_count": null, "id": "d6e7638e-9380-45ac-8809-9fd4da71be46", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5\n", ")" ] }, { "cell_type": "markdown", "id": "98614120-85e4-4d6c-b1b0-3f03755e094e", "metadata": {}, "source": [ "Perhaps the size of the image is roughly correct, but we want to reduce the distance between node levels; we can scale the level spacing with `level_scaling`:" ] }, { "cell_type": "code", "execution_count": null, "id": "0abb278d-2887-46fd-b9c3-0dc987d2da25", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75\n", ")" ] }, { "cell_type": "markdown", "id": "f0991616-248f-4f90-b1ef-492d93d9db67", "metadata": {}, "source": [ "The player labels are looking a little cramped. Let's adjust the width by increasing the `width_scaling`:" ] }, { "cell_type": "code", "execution_count": null, "id": "7cb624c2-b3c3-4775-b1cd-7ef0e9d24eb1", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25\n", ")" ] }, { "cell_type": "markdown", "id": "7e06766f-91aa-4eea-aca8-d4ef8d8270b0", "metadata": {}, "source": [ "If we want to use color in our image, we can set the `color_scheme`. Here let's use the \"gambit\" color scheme:" ] }, { "cell_type": "code", "execution_count": null, "id": "6d326b08-87e2-4d49-80bf-e16981ee221f", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\"\n", ")" ] }, { "cell_type": "markdown", "id": "35b1415d-84b9-45c2-a4e0-a05f04651042", "metadata": {}, "source": [ "An advantage to using a color scheme is that nodes no longer require player labels, which are handled by the legend, de-cluttering the image further.\n", "\n", "Let's make our image more striking by increasing the `edge_thickness`:" ] }, { "cell_type": "code", "execution_count": null, "id": "c7aec967-77f5-434d-bb83-73c8518dd997", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\",\n", " edge_thickness=1.5\n", ")" ] }, { "cell_type": "markdown", "id": "eec80871-03cd-4f8b-9b47-3d4a4ad16ce5", "metadata": {}, "source": [ "One final adjustment we could make would be to adjust the positioning of action labels on the image.\n", "This can be helpful in cases where the action labels overlap visually with information sets boundaries or other features.\n", "The default value of 0.5 places the labels halfway along the edges, which for this game looks about right, but we can change this by setting `action_label_position`:" ] }, { "cell_type": "code", "execution_count": null, "id": "0f82b80c-8f7d-41ff-9e24-ffb1524a95be", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\",\n", " edge_thickness=1.5,\n", " action_label_position=0.6\n", ")" ] }, { "cell_type": "markdown", "id": "f77731a4-1c3a-4e83-a69e-b3b8404059b5", "metadata": {}, "source": [ "## Saving images\n", "\n", "Once we are happy with our image, we can save it as a Tex file, or generate a PNG or PDF with the rendered image.\n", "Each of the following functions takes the same arguments as the `draw_tree` examples above.\n", "Setting the `save_to` argument will determine where the `.ef` file used by `draw_tree` to preserve layout information is saved, as well as the output image or Tex file:" ] }, { "cell_type": "code", "execution_count": null, "id": "e6045291-653e-4702-a95c-5c00159d4b43", "metadata": {}, "outputs": [], "source": [ "draw_tree(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\",\n", " edge_thickness=1.5,\n", " action_label_position=0.6,\n", " save_to=\"2smp\" # Creates 2smp.ef\n", ")" ] }, { "cell_type": "markdown", "id": "d21634cc-64fd-4eed-8887-b4e3a80734fd", "metadata": {}, "source": [ "### Save to TeX\n", "\n", "```python\n", "from draw_tree generate_tex\n", "generate_tex(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\",\n", " edge_thickness=1.5,\n", " action_label_position=0.6,\n", " save_to=\"2smp\" # Creates 2smp.ef and 2smp.tex\n", ")\n", "```\n", "\n", "### Save to PDF\n", "\n", "```python\n", "from draw_tree import generate_pdf\n", "generate_pdf(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\",\n", " edge_thickness=1.5,\n", " action_label_position=0.6,\n", " save_to=\"2smp\" # Creates 2smp.ef and 2smp.pdf\n", ")\n", "```\n", "\n", "### Save to PNG\n", "\n", "```python\n", "from draw_tree import generate_png\n", "generate_png(\n", " g,\n", " shared_terminal_depth=True,\n", " scale_factor=0.5,\n", " level_scaling=0.75,\n", " width_scaling=1.25,\n", " color_scheme=\"gambit\",\n", " edge_thickness=1.5,\n", " action_label_position=0.6,\n", " save_to=\"2smp\" # Creates 2smp.ef and 2smp.png\n", ")\n", "```" ] }, { "cell_type": "markdown", "id": "0fa1bb4f-4dc4-4619-b20a-f84948a69185", "metadata": {}, "source": [ "## Further adjustments to game images\n", "\n", "If your image requires further adjustments, you can manually edit your game's `.ef` file.\n", "You can find information on EF format specs in the [draw_tree docs](https://github.com/gambitproject/draw_tree).\n", "\n", "EF files that are manually created or (exported from [Game Theory Explorer](https://gametheoryexplorer-a68c7.web.app/) can be drawn by `draw_tree` with the same functions explored in this tutorial, but you should drop the formatting parameters:\n", "\n", "```python\n", "draw_tree('path/to/game.ef')\n", "generate_tex('path/to/game.ef')\n", "generate_pdf('path/to/game.ef')\n", "generate_png('path/to/game.ef')\n", "```" ] } ], "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.13.5" } }, "nbformat": 4, "nbformat_minor": 5 }