{ "cells": [ { "cell_type": "markdown", "id": "e3a17a73-a2c7-4b21-b242-22b1844e33df", "metadata": {}, "source": [ "# `LaPDXYExclusion` Overview" ] }, { "cell_type": "code", "execution_count": null, "id": "9e0a519a-1b16-4242-99f1-2cfd036802fb", "metadata": {}, "outputs": [], "source": [ "%matplotlib inline" ] }, { "cell_type": "code", "execution_count": null, "id": "46416d10-4fd6-4454-a1c1-f3b9f1826ad6", "metadata": {}, "outputs": [], "source": [ "import numpy as np\n", "import matplotlib.pyplot as plt\n", "import sys\n", "import xarray as xr\n", "\n", "from matplotlib.patches import Polygon\n", "\n", "sys.executable;" ] }, { "cell_type": "code", "execution_count": null, "id": "0c757daf-b507-4119-acbe-135a6a91d197", "metadata": {}, "outputs": [], "source": [ "try:\n", " from bapsf_motion.motion_builder.exclusions import (\n", " CircularExclusion,\n", " DividerExclusion,\n", " GovernExclusion,\n", " LaPDXYExclusion,\n", " )\n", "except ModuleNotFoundError:\n", " from pathlib import Path\n", "\n", " HERE = Path().cwd()\n", " BAPSF_MOTION = (HERE / \"..\" / \"..\" / \"..\" ).resolve()\n", " sys.path.append(str(BAPSF_MOTION))\n", " \n", " from bapsf_motion.motion_builder.exclusions import (\n", " CircularExclusion,\n", " DividerExclusion,\n", " GovernExclusion,\n", " LaPDXYExclusion,\n", " )\n", " " ] }, { "cell_type": "code", "execution_count": null, "id": "6ec82b7e-8d2c-4d1c-a4b6-b68d0c359109", "metadata": {}, "outputs": [], "source": [ "plt.rcParams.update(\n", " {\n", " # \"figure.figsize\": [12, 0.56 * 12],\n", " \"figure.figsize\": [10, 0.8 * 10],\n", " \"font.size\": 16,\n", " }\n", ")" ] }, { "cell_type": "markdown", "id": "72ee8d1f-86d3-436d-9a7d-35cd67726ab3", "metadata": { "tags": [] }, "source": [ "## Usage\n", "\n", "Direct usage should never be needed, since the `MotionBuilder` will handle this given the correct configuration is given to `MotionBuilder`. The appropriate TOML or dictionary like configurations can be found in the documentation for `LaPDXYExclusion`." ] }, { "cell_type": "markdown", "id": "f41677ae-74cc-488f-9279-610a019844ac", "metadata": { "tags": [] }, "source": [ "### Is a `GovernExclusion`\n", "\n", "`LaPDXYExclusion` is a subclass of `GovernExclusion`. This means the mask generated by `LaPDXYExclusion` will examine the existing global mask to generate its own mask, and that generated mask will replace the global mask. As a result, there should only be one `GovernExclusion` used wheneve constructing a motion space." ] }, { "cell_type": "code", "execution_count": null, "id": "4eb794d2-9ee5-44f0-9d95-5a3ab560166a", "metadata": {}, "outputs": [], "source": [ "issubclass(LaPDXYExclusion, GovernExclusion)" ] }, { "cell_type": "markdown", "id": "c8ca7a05-f25a-489f-84fe-adec1924c181", "metadata": {}, "source": [ "### Is a Compound Exclusion\n", "\n", "This means `LaPDXYExclusion` leverages other exclusion classes to generate its exclusion layer. These exclusions can be view with the `composed_exclusions` attribute, which you can see in the next section." ] }, { "cell_type": "markdown", "id": "10b0ccfd-6f1d-446e-980d-f1bfda05c468", "metadata": {}, "source": [ "### Defining a `LaPDXYExclusion`\n", "\n", "Create an initial global mask." ] }, { "cell_type": "code", "execution_count": null, "id": "21e8a9b3-d12d-48e1-8b41-2312959b1ae2", "metadata": {}, "outputs": [], "source": [ "size = 111\n", "side = np.linspace(-55, 55, num=size)\n", "ds = xr.Dataset(\n", " {\"mask\": ((\"x\", \"y\"), np.ones((size, size), dtype=bool))},\n", " coords={\n", " \"x\": side,\n", " \"y\": side,\n", " },\n", ")" ] }, { "cell_type": "markdown", "id": "7cb0d223-eab1-491c-afe8-674df3d1236b", "metadata": {}, "source": [ "The default configuration parameters for `LaPDXYExclusion` define a probe drive beting deployed on the East side of the LaPD." ] }, { "cell_type": "code", "execution_count": null, "id": "2391fb98-821a-4478-8f03-d9147b7cee1e", "metadata": {}, "outputs": [], "source": [ "ex = LaPDXYExclusion(ds)\n", "\n", "ds.mask.plot(x=\"x\", y=\"y\");\n", "plt.scatter(\n", " ex.insertion_point[0],\n", " ex.insertion_point[1],\n", " marker=\"+\",\n", " color=\"black\",\n", " s=8**2,\n", ")\n", "axis = plt.gca()\n", "axis.set_xlim(-60, 60)\n", "axis.set_ylim(-60, 60)" ] }, { "cell_type": "markdown", "id": "3376fbd9-4423-4f4a-b315-8c1f5047212f", "metadata": {}, "source": [ "The configuration dictionary for this exclusion looks like..." ] }, { "cell_type": "code", "execution_count": null, "id": "3356af46-d169-49c8-b657-d0c851e4db55", "metadata": {}, "outputs": [], "source": [ "ex.config" ] }, { "cell_type": "markdown", "id": "b3060bfc-8e21-4879-80e8-b86d89fd0341", "metadata": {}, "source": [ "You can see the exclusion is composed of 4 other exclusions, 1x `Shadow2DExclusion`, 1x `CircularExclusion`, and 3x `DividerExclusions`." ] }, { "cell_type": "code", "execution_count": null, "id": "96f32dfb-25a6-4166-9496-1e6d156471e2", "metadata": {}, "outputs": [], "source": [ "ex.composed_exclusions" ] }, { "cell_type": "markdown", "id": "b8de7e2f-6dd8-4752-acf3-2bf05e774776", "metadata": {}, "source": "Let's make a slightly more complicated LaPD exclusion layer. In this \"complicated\" scenario let's assume the probe drive is being deployed on the West side of the LaPD and there is a circular obstruction at the center of the chamber." }, { "cell_type": "code", "execution_count": null, "id": "71c91201-9dbc-492c-842f-9cab2a907fdc", "metadata": {}, "outputs": [], "source": [ "# Reset the motion space\n", "size = 111\n", "side = np.linspace(-55, 55, num=size)\n", "ds = xr.Dataset(\n", " {\"mask\": ((\"x\", \"y\"), np.ones((size, size), dtype=bool))},\n", " coords={\n", " \"x\": side,\n", " \"y\": side,\n", " },\n", ")\n", "\n", "# Add circular obstruction at the center\n", "ex_1 = CircularExclusion(ds, radius=5, center=(0,0), exclude=\"inside\")\n", "\n", "# Define West side lapd XY exclusion\n", "ex = LaPDXYExclusion(ds, port_location=\"W\")\n", "\n", "# plot mask\n", "ds.mask.plot(x=\"x\", y=\"y\");\n", "plt.scatter(\n", " ex.insertion_point[0],\n", " ex.insertion_point[1],\n", " marker=\"+\",\n", " color=\"black\",\n", " s=8**2,\n", ")\n", "axis = plt.gca()\n", "axis.set_xlim(-60, 60)\n", "axis.set_ylim(-60, 60)" ] }, { "cell_type": "markdown", "id": "978453e6-0fe4-4120-8ecc-2414c4171be6", "metadata": {}, "source": [ "Now you can see the component `Shadow2DExclusion` is casting a shadow from the center circular exclusion, so the probe can not be moved to that location.\n", "\n", "The confiruation for this setup looks like..." ] }, { "cell_type": "code", "execution_count": null, "id": "f6f7e4f7-cf6d-4e05-bbac-678eb881a029", "metadata": {}, "outputs": [], "source": [ "ex.config" ] } ], "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.9.13" } }, "nbformat": 4, "nbformat_minor": 5 }