{
  "cells": [
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "%matplotlib inline"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "\n# Structure of ring network\n\nThis example illustrates the structure of the ring network used by\n:cite:t:`senk2020`.\nMean-field results of this model are shown in the examples\n:doc:`mapping_lif_rate` and :doc:`spatial_patterns`.\n"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Here, we use the Python package ``svgutils`` to integrate an externally\ngenerated network sketch into the figure.\nThis package is not part of the default Python environment of NNMT.\nIn the end of the script, we use the external tool ``inkscape`` via the\ncommand line to convert from ``svg`` format to ``eps``.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "import os\nimport sys\nfrom nnmt.models.basic import Basic as BasicNetwork\nimport numpy as np\nimport matplotlib as mpl\nimport matplotlib.gridspec as gridspec\nimport matplotlib.pyplot as plt\nfrom matplotlib.patches import Circle\nplt.style.use('frontiers.mplstyle')\nmpl.rcParams.update({'legend.fontsize': 'medium',  # old: 5.0 was too small\n                     'axes.titlepad': 0.0})\ntry:\n    import svgutils.transform as sg\nexcept BaseException:\n    pass\n\nassert 'svgutils' in sys.modules, (\n    'This figure requires: \"import svgutils.transform as sg\"')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "First, we define plotting parameters.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "params = {\n    # figure file name (without extension)\n    'figure_fn': 'network_structure',\n\n    # file name of external sketch\n    'sketch_fn': 'network_sketch.svg',\n\n    # figure width in inch\n    'figwidth_1col': 85. / 25.4,\n\n    # label and corresponding scaling parameter for plotted quantities\n    'quantities': {\n        'displacement': {\n            'label': 'displacement $d$ (mm)',\n            'scale': 1e3}},\n\n    # colors for excitation and inhibition\n    'colors': {\n        'ex_blue': '#4C72B0',\n        'inh_red': '#C44E52'}}"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "We also define a helper function for adding labels to figure panels.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def _add_label(ax, label, xshift=0., yshift=0., scale_fs=1.):\n    \"\"\"\n    Adds label to plot panel given by axis.\n\n    Parameters:\n    -----------\n    ax : matplotlib.axes.Axes object\n        Axes.\n    label : str\n        Letter.\n    xshift : float\n        x-shift of label position.\n    yshift : float\n        y-shift of label position.\n    scale_fs : float\n        Scale factor for font size.\n    \"\"\"\n    label_pos = [0., 1.]\n    ax.text(label_pos[0] + xshift, label_pos[1] + yshift, label,\n            ha='left', va='bottom',\n            transform=ax.transAxes, fontweight='bold',\n            fontsize=mpl.rcParams['font.size'] * scale_fs)"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "The figure to illustrate the network structure spans one column.\nIt is divided into three panels.\nPanel A contains the external network sketch which we will add in after\nthe other panels will be completed.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "fig = plt.figure(figsize=(params['figwidth_1col'], params['figwidth_1col']))\ngs = gridspec.GridSpec(2, 2, figure=fig, wspace=0.2, hspace=0)\n\n# panel for external network sketch\n_add_label(plt.subplot(gs[0, :]), 'A', xshift=-0.04, yshift=-0.1)\nplt.gca().set_axis_off()"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In panel B, we illustrate the ring-like network structure.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "ax = plt.subplot(gs[1, 0])\n_add_label(ax, 'B', xshift=-0.085)\n\ncirc = Circle(xy=(0, 0), radius=1, color='k', fill=False)\nax.add_artist(circ)\n\nblue = params['colors']['ex_blue']\nred = params['colors']['inh_red']\n\nn_in = 10\nex2in = 4\n\nstep = 2 * np.pi / n_in\n\noffset = 0\nfor i in np.arange(1 + ex2in):\n    if i == 0:  # inh.\n        marker = 'o'\n        color = red\n    else:  # exc.\n        marker = '^'\n        color = blue\n\n    xy = []\n    for i in np.arange(n_in):\n        x = (1 + offset) * np.cos(i * step)\n        y = (1 + offset) * np.sin(i * step)\n        xy.append([x, y])\n    xy = np.array(xy)\n\n    ax.plot(xy[:, 0], xy[:, 1],\n            marker=marker, markersize=mpl.rcParams['lines.markersize'],\n            linestyle='', color=color)\n    offset += 0.2\n\nax.annotate('ring\\n network', (0, 0), va='center', ha='center')\n\nlim = 2\nax.set_xlim(-lim, lim)\nax.set_ylim(-lim, lim)\nax.set_aspect('equal')\n\nplt.axis('off')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "In panel C, we illustrate the boxcar-shaped spatial connectivity profile.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "def _get_p(rs, width):\n    p = np.zeros(len(rs))\n    # p is normalized to 1\n    height = 1. / (2 * width)\n    p[np.where(np.abs(rs) <= width)] = height\n    return p\n\n\ngs_prof = gs[1, 1].subgridspec(4, 1)\nax = plt.subplot(gs_prof[1:3])\n_add_label(ax, 'C', yshift=1.08)\n\nblue = params['colors']['ex_blue']\nred = params['colors']['inh_red']\n\nnetwork = BasicNetwork(\n    network_params='Senk2020_network_params.yaml',\n    analysis_params='Senk2020_analysis_params.yaml')\newidth = network.network_params['width'][0] * \\\n    params['quantities']['displacement']['scale']\niwidth = network.network_params['width'][1] * \\\n    params['quantities']['displacement']['scale']\n\nmax_x = np.max([ewidth, iwidth])\nrs = np.arange(-1.5 * max_x, 1.5 * max_x, 1e-5)  # in mm\n\nep = _get_p(rs, ewidth)\nip = _get_p(rs, iwidth)\nax.plot(rs, ep, blue)\nax.plot(rs, ip, red)\n\nxstp = ewidth / 6.\nax.annotate('E',\n            [ewidth + xstp, 1. / (2. * ewidth)],\n            color=blue,\n            va='top', ha='left')\n\nax.annotate('I',\n            [iwidth + xstp, 1. / (2. * iwidth)],\n            color=red,\n            va='top', ha='left')\n\nax.set_xlim(rs[0], rs[-1])\nax.set_xlabel(params['quantities']['displacement']['label'])\nax.get_yaxis().set_visible(False)\nax.spines['left'].set_visible(False)\nax.set_title('connection\\n probability $p$')"
      ]
    },
    {
      "cell_type": "markdown",
      "metadata": {},
      "source": [
        "Finally, the external network sketch is included and the figure is saved to\nfile.\n\n"
      ]
    },
    {
      "cell_type": "code",
      "execution_count": null,
      "metadata": {
        "collapsed": false
      },
      "outputs": [],
      "source": [
        "svg_mpl = sg.from_mpl(fig, savefig_kw=dict(transparent=False))\nw_svg, h_svg = svg_mpl.get_size()\nsvg_mpl.set_size((w_svg + 'pt', h_svg + 'pt'))\nsvg_sketch = sg.fromfile(params['sketch_fn']).getroot()\nsvg_sketch.moveto(x=50, y=10, scale_x=1.5)\nsvg_mpl.append(svg_sketch)\nsvg_mpl.save(f\"{params['figure_fn']}.svg\")\nos_return = os.system(\n    f\"inkscape --export-eps={params['figure_fn']}.eps {params['figure_fn']}.svg\")\nif os_return == 0:\n    os.remove(f\"{params['figure_fn']}.svg\")\nelse:\n    print('Conversion to eps using inkscape failed, keeping svg.')"
      ]
    }
  ],
  "metadata": {
    "kernelspec": {
      "display_name": "Python 3",
      "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.9.13"
    }
  },
  "nbformat": 4,
  "nbformat_minor": 0
}