{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "859711e6",
   "metadata": {},
   "source": [
    "# Regions & Locsets\n",
    "\n",
    "When you decorate a multi-compartment cell you must say **where** a mechanism\n",
    "goes. `braincell` answers this with two kinds of selection expression, both\n",
    "living in {mod}`braincell.filter`:\n",
    "\n",
    "- a **region** selects an *extended set of cable* — \"the soma\", \"all apical\n",
    "  dendrites\", \"everything within 100 µm of the root\". You `paint` density\n",
    "  mechanisms onto regions.\n",
    "- a **locset** selects a *set of points* — \"the root\", \"all branch tips\",\n",
    "  \"every 50 µm\". You `place` point mechanisms onto locsets."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ed597a71",
   "metadata": {},
   "outputs": [],
   "source": [
    "import braincell.filter as f"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "bf0a3ffa",
   "metadata": {},
   "source": [
    "```{note}\n",
    "This mirrors the *labels* idea in simulators like Arbor: a small, composable\n",
    "algebra for naming parts of a morphology, kept separate from the mechanisms you\n",
    "attach to them.\n",
    "```\n",
    "\n",
    "## Regions (paint targets)\n",
    "\n",
    "```{list-table}\n",
    ":header-rows: 1\n",
    ":widths: 34 66\n",
    "\n",
    "* - Expression\n",
    "  - Selects\n",
    "* - {class}`~braincell.filter.AllRegion`\n",
    "  - the entire cell\n",
    "* - {class}`~braincell.filter.EmptyRegion`\n",
    "  - nothing (useful as an identity in set operations)\n",
    "* - {func}`~braincell.filter.branch_in`\n",
    "  - branches matching a property, e.g. `branch_in(\"type\", \"soma\")`\n",
    "* - {func}`~braincell.filter.branch_range` / {class}`~braincell.filter.BranchRangeFilter`\n",
    "  - a sub-interval along branches\n",
    "* - {class}`~braincell.filter.SubtreeRegion`\n",
    "  - a branch and everything distal to it\n",
    "* - {class}`~braincell.filter.RadiusRangeRegion`\n",
    "  - cable whose radius falls in a range\n",
    "* - {class}`~braincell.filter.EuclideanDistanceRegion` / {class}`~braincell.filter.TreeDistanceRegion`\n",
    "  - cable within a straight-line / along-the-tree distance\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ad35942e",
   "metadata": {},
   "outputs": [],
   "source": [
    "from braincell.filter import AllRegion, branch_in\n",
    "\n",
    "cell.paint(AllRegion(), mech.Channel(\"IL\", g_max=0.0003 * u.S / u.cm**2, E=-70. * u.mV))\n",
    "cell.paint(branch_in(\"type\", \"soma\"), mech.Channel(\"Na_Ba2002\", g_max=0.12 * u.S / u.cm**2))\n",
    "cell.paint(\n",
    "    branch_in(\"type\", (\"dendrite\", \"basal_dendrite\", \"apical_dendrite\")),\n",
    "    mech.Channel(\"CaL_IS2008\", g_max=0.002 * u.S / u.cm**2),\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d5163b09",
   "metadata": {},
   "source": [
    "## Locsets (place targets)\n",
    "\n",
    "```{list-table}\n",
    ":header-rows: 1\n",
    ":widths: 34 66\n",
    "\n",
    "* - Expression\n",
    "  - Selects\n",
    "* - {class}`~braincell.filter.RootLocation`\n",
    "  - a point on the root branch, e.g. `RootLocation(0.5)` (the midpoint)\n",
    "* - {class}`~braincell.filter.Terminals`\n",
    "  - all terminal tips\n",
    "* - {class}`~braincell.filter.BranchPoints`\n",
    "  - all branch points (bifurcations)\n",
    "* - {class}`~braincell.filter.UniformSamples` / {class}`~braincell.filter.StepSamples`\n",
    "  - evenly / step-spaced points along the cell\n",
    "* - {class}`~braincell.filter.RandomSamples`\n",
    "  - randomly sampled points\n",
    "* - {func}`~braincell.filter.at` / {class}`~braincell.filter.AtLocation`\n",
    "  - a specific (branch, position) location\n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7dbf7d43",
   "metadata": {},
   "outputs": [],
   "source": [
    "from braincell.filter import RootLocation, Terminals\n",
    "\n",
    "cell.place(RootLocation(0.5), mech.CurrentClamp(durations=50 * u.ms, amplitudes=0.2 * u.nA))\n",
    "cell.place(Terminals(), mech.StateProbe(\"V\"))"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "5eb80ab9",
   "metadata": {},
   "source": [
    "## Composing selections\n",
    "\n",
    "Both regions and locsets support **set operations** — union, intersection,\n",
    "difference — so you can build precise targets from simple parts\n",
    "({class}`~braincell.filter.RegionSetOp`, {class}`~braincell.filter.LocsetSetOp`,\n",
    "and the mask variants). This is the same composability that makes mechanisms\n",
    "reusable: name a place once, decorate it many times.\n",
    "\n",
    "`braincell.filter` also caches selection results\n",
    "({class}`~braincell.filter.SelectionCache`) so repeated paints over the same\n",
    "region don't recompute the membership.\n",
    "\n",
    "## See also\n",
    "\n",
    "- {doc}`mechanisms` — the things you paint and place.\n",
    "- {doc}`morphology` — what the selections range over.\n",
    "- {doc}`../apis/filter` — full selection API reference."
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "name": "python"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
