diff --git a/.github/workflows/stale_marker.yml b/.github/workflows/stale_marker.yml new file mode 100644 index 00000000000..7affbb8bebf --- /dev/null +++ b/.github/workflows/stale_marker.yml @@ -0,0 +1,19 @@ +name: "Close stale issues and PR" +on: + schedule: + - cron: "30 1 * * *" + +jobs: + stale: + runs-on: ubuntu-latest + steps: + - uses: actions/stale@v4 + with: + stale-issue-message: "This issue is stale because it has been open 90 days with no activity. Remove stale label or comment or this will be closed in 7 days." + stale-pr-message: "This PR is stale because it has been open 90 days with no activity." + close-issue-message: "This issue was closed because it has been stalled for 30 days with no activity." + days-before-issue-stale: 90 + days-before-pr-stale: 90 + days-before-issue-close: 30 + days-before-pr-close: -1 + start-date: "2022-02-15T00:00:00Z" diff --git a/OTE_landing_page.md b/OTE_landing_page.md new file mode 100644 index 00000000000..7b1aa7bd64b --- /dev/null +++ b/OTE_landing_page.md @@ -0,0 +1,80 @@ +# OpenVINO™ Training Extensions {#ote_documentation} +[![python](https://img.shields.io/badge/python-3.8%2B-green)]() +[![black](https://img.shields.io/badge/code%20style-black-000000.svg)]() +[![mypy](https://img.shields.io/badge/%20type_checker-mypy-%231674b1?style=flat)]() +[![openvino](https://img.shields.io/badge/openvino-2021.4-purple)]() + +OpenVINO™ Training Extensions (OTE) provide a suite of advanced algorithms to train +Deep Learning models and convert them using the [OpenVINO™ +toolkit](https://software.intel.com/en-us/openvino-toolkit) for optimized +inference. It allows you to export and convert the models to the needed format. OTE independently create and train the model. It is open-sourced and available on [GitHub](https://github.com/openvinotoolkit/training_extensions). + +## Detailed Workflow +![](training_extensions_framework.png) + +1. To start working with OTE, prepare and annotate your dataset. For example, on CVAT. + +2. OTE train the model, using training interface, and evaluate the model quality on your dataset, using evaluation and inference interfaces. + +Note: prepare a separate dataset or split the dataset you have for more accurate quality evaluation. + +3. Having successful evaluation results received, you have an opportunity to deploy your model or continue optimizing it, using NNCF and POT. For more information about these frameworks, go to [Optimization Guide](https://docs.openvino.ai/nightly/openvino_docs_model_optimization_guide.html). + +If the results are unsatisfactory, add datasets and perform the same steps, starting with dataset annotation. + +## OTE Components +* [OTE SDK](https://github.com/openvinotoolkit/training_extensions/tree/master/ote_sdk) +* [OTE CLI](https://github.com/openvinotoolkit/training_extensions/tree/master/ote_cli) +* [OTE Algorithms](https://github.com/openvinotoolkit/training_extensions/tree/master/external) + +## Get Started +## Prerequisites +* Ubuntu 18.04 / 20.04 +* Python 3.8+ +* [CUDA Toolkit 11.1](https://developer.nvidia.com/cuda-11.1.1-download-archive) - for training on GPU +In order to get started with OpenVINO™ Training Extensions click [here](QUICK_START_GUIDE.md). + +## Installation + +1. Clone repository in the working directory by running the following: + ``` + git clone https://github.com/openvinotoolkit/training_extensions.git + cd training_extensions + git checkout -b develop origin/develop + git submodule update --init --recursive + ``` + +2. Install prerequisites by running the following: + ``` + sudo apt-get install python3-pip python3-venv + ``` + +3. Search for available scripts that create python virtual environments for different task types: + ```bash + find external/ -name init_venv.sh + ``` + + Sample output: + ``` + external/mmdetection/init_venv.sh + external/mmsegmentation/init_venv.sh + external/deep-object-reid/init_venv.sh + ``` + +4. Create, activate Object Detection virtual environment, and install `ote_cli`: + ``` + ./external/mmdetection/init_venv.sh det_venv + source det_venv/bin/activate + pip3 install -e ote_cli/ + ``` +To learn more about OTE CLI commands go to [GitHub](https://github.com/openvinotoolkit/training_extensions/blob/master/QUICK_START_GUIDE.md). + +## Tutorials +[Object Detection](https://github.com/openvinotoolkit/training_extensions/blob/master/ote_cli/notebooks/train.ipynb) + +## Contribution +If you want to contribute, refer to [Contributing guide](https://github.com/openvinotoolkit/training_extensions/blob/master/CONTRIBUTING.md) before starting work on a pull request. + +Deep Learning Deployment Toolkit is licensed under [Apache License Version 2.0](https://github.com/openvinotoolkit/training_extensions/blob/master/LICENSE). +By contributing to the project, you agree to the license and copyright terms therein +and release your contribution under these terms. diff --git a/data/anomaly/test.json b/data/anomaly/classification/test.json similarity index 100% rename from data/anomaly/test.json rename to data/anomaly/classification/test.json diff --git a/data/anomaly/train.json b/data/anomaly/classification/train.json similarity index 100% rename from data/anomaly/train.json rename to data/anomaly/classification/train.json diff --git a/data/anomaly/val.json b/data/anomaly/classification/val.json similarity index 100% rename from data/anomaly/val.json rename to data/anomaly/classification/val.json diff --git a/data/anomaly/segmentation/test.json b/data/anomaly/segmentation/test.json new file mode 100644 index 00000000000..279a2002567 --- /dev/null +++ b/data/anomaly/segmentation/test.json @@ -0,0 +1,16564 @@ +{ + "image_path": { + "1": "test/good/004.png", + "2": "test/good/005.png", + "3": "test/good/006.png", + "4": "test/good/007.png", + "5": "test/good/008.png", + "6": "test/good/009.png", + "7": "test/star/004.png", + "8": "test/star/005.png", + "9": "test/star/006.png", + "10": "test/star/007.png", + "11": "test/star/008.png", + "12": "test/star/009.png", + "13": "test/hexagon/004.png", + "14": "test/hexagon/005.png", + "15": "test/hexagon/006.png", + "16": "test/hexagon/007.png", + "17": "test/hexagon/008.png", + "18": "test/hexagon/009.png" + }, + "label": { + "1": "good", + "2": "good", + "3": "good", + "4": "good", + "5": "good", + "6": "good", + "7": "star", + "8": "star", + "9": "star", + "10": "star", + "11": "star", + "12": "star", + "13": "hexagon", + "14": "hexagon", + "15": "hexagon", + "16": "hexagon", + "17": "hexagon", + "18": "hexagon" + }, + "masks": { + "7": [ + [ + [ + 0.2578125, + 0.1953125 + ], + [ + 0.2578125, + 0.203125 + ], + [ + 0.2578125, + 0.2109375 + ], + [ + 0.2578125, + 0.21875 + ], + [ + 0.2578125, + 0.2265625 + ], + [ + 0.265625, + 0.234375 + ], + [ + 0.2578125, + 0.2421875 + ], + [ + 0.25, + 0.2421875 + ], + [ + 0.2421875, + 0.234375 + ], + [ + 0.234375, + 0.234375 + ], + [ + 0.2265625, + 0.2265625 + ], + [ + 0.21875, + 0.2265625 + ], + [ + 0.2109375, + 0.21875 + ], + [ + 0.203125, + 0.21875 + ], + [ + 0.1953125, + 0.2109375 + ], + [ + 0.1953125, + 0.21875 + ], + [ + 0.1953125, + 0.2265625 + ], + [ + 0.1953125, + 0.234375 + ], + [ + 0.1953125, + 0.2421875 + ], + [ + 0.1953125, + 0.25 + ], + [ + 0.203125, + 0.2578125 + ], + [ + 0.203125, + 0.265625 + ], + [ + 0.203125, + 0.2734375 + ], + [ + 0.203125, + 0.28125 + ], + [ + 0.203125, + 0.2890625 + ], + [ + 0.203125, + 0.296875 + ], + [ + 0.2109375, + 0.3046875 + ], + [ + 0.2109375, + 0.3125 + ], + [ + 0.2109375, + 0.3203125 + ], + [ + 0.2109375, + 0.328125 + ], + [ + 0.2109375, + 0.3359375 + ], + [ + 0.2109375, + 0.34375 + ], + [ + 0.21875, + 0.3515625 + ], + [ + 0.21875, + 0.359375 + ], + [ + 0.21875, + 0.3671875 + ], + [ + 0.21875, + 0.375 + ], + [ + 0.21875, + 0.3828125 + ], + [ + 0.21875, + 0.390625 + ], + [ + 0.2265625, + 0.3984375 + ], + [ + 0.2265625, + 0.40625 + ], + [ + 0.2265625, + 0.4140625 + ], + [ + 0.2265625, + 0.421875 + ], + [ + 0.2265625, + 0.4296875 + ], + [ + 0.21875, + 0.4375 + ], + [ + 0.2109375, + 0.4453125 + ], + [ + 0.203125, + 0.453125 + ], + [ + 0.1953125, + 0.4609375 + ], + [ + 0.1875, + 0.46875 + ], + [ + 0.1796875, + 0.4765625 + ], + [ + 0.171875, + 0.484375 + ], + [ + 0.1640625, + 0.4921875 + ], + [ + 0.15625, + 0.5 + ], + [ + 0.1640625, + 0.5 + ], + [ + 0.171875, + 0.5 + ], + [ + 0.1796875, + 0.5 + ], + [ + 0.1875, + 0.5 + ], + [ + 0.1953125, + 0.5 + ], + [ + 0.203125, + 0.5 + ], + [ + 0.2109375, + 0.5 + ], + [ + 0.21875, + 0.5078125 + ], + [ + 0.2109375, + 0.515625 + ], + [ + 0.203125, + 0.5234375 + ], + [ + 0.1953125, + 0.53125 + ], + [ + 0.1875, + 0.5390625 + ], + [ + 0.1796875, + 0.546875 + ], + [ + 0.171875, + 0.5546875 + ], + [ + 0.1640625, + 0.5625 + ], + [ + 0.15625, + 0.5703125 + ], + [ + 0.1484375, + 0.578125 + ], + [ + 0.140625, + 0.5859375 + ], + [ + 0.1328125, + 0.59375 + ], + [ + 0.125, + 0.59375 + ], + [ + 0.1171875, + 0.6015625 + ], + [ + 0.109375, + 0.609375 + ], + [ + 0.1015625, + 0.6171875 + ], + [ + 0.09375, + 0.625 + ], + [ + 0.0859375, + 0.6328125 + ], + [ + 0.078125, + 0.640625 + ], + [ + 0.0703125, + 0.6484375 + ], + [ + 0.0625, + 0.65625 + ], + [ + 0.0546875, + 0.6640625 + ], + [ + 0.046875, + 0.671875 + ], + [ + 0.0390625, + 0.6796875 + ], + [ + 0.03125, + 0.6875 + ], + [ + 0.0390625, + 0.6875 + ], + [ + 0.046875, + 0.6875 + ], + [ + 0.0546875, + 0.6875 + ], + [ + 0.0625, + 0.6875 + ], + [ + 0.0703125, + 0.6875 + ], + [ + 0.078125, + 0.6875 + ], + [ + 0.0859375, + 0.6953125 + ], + [ + 0.09375, + 0.6953125 + ], + [ + 0.1015625, + 0.6953125 + ], + [ + 0.109375, + 0.6953125 + ], + [ + 0.1171875, + 0.6953125 + ], + [ + 0.125, + 0.6953125 + ], + [ + 0.1328125, + 0.6953125 + ], + [ + 0.140625, + 0.703125 + ], + [ + 0.1484375, + 0.703125 + ], + [ + 0.15625, + 0.703125 + ], + [ + 0.1640625, + 0.703125 + ], + [ + 0.171875, + 0.703125 + ], + [ + 0.1796875, + 0.703125 + ], + [ + 0.1875, + 0.703125 + ], + [ + 0.1953125, + 0.703125 + ], + [ + 0.203125, + 0.7109375 + ], + [ + 0.2109375, + 0.7109375 + ], + [ + 0.21875, + 0.7109375 + ], + [ + 0.2265625, + 0.7109375 + ], + [ + 0.234375, + 0.7109375 + ], + [ + 0.2421875, + 0.7109375 + ], + [ + 0.25, + 0.7109375 + ], + [ + 0.2578125, + 0.71875 + ], + [ + 0.265625, + 0.71875 + ], + [ + 0.2734375, + 0.71875 + ], + [ + 0.28125, + 0.71875 + ], + [ + 0.2890625, + 0.71875 + ], + [ + 0.296875, + 0.71875 + ], + [ + 0.3046875, + 0.71875 + ], + [ + 0.3125, + 0.71875 + ], + [ + 0.3203125, + 0.7265625 + ], + [ + 0.3203125, + 0.734375 + ], + [ + 0.3203125, + 0.7421875 + ], + [ + 0.328125, + 0.75 + ], + [ + 0.328125, + 0.7578125 + ], + [ + 0.3359375, + 0.765625 + ], + [ + 0.3359375, + 0.7734375 + ], + [ + 0.34375, + 0.78125 + ], + [ + 0.34375, + 0.7890625 + ], + [ + 0.3515625, + 0.796875 + ], + [ + 0.3515625, + 0.8046875 + ], + [ + 0.359375, + 0.8125 + ], + [ + 0.359375, + 0.8203125 + ], + [ + 0.3671875, + 0.828125 + ], + [ + 0.3671875, + 0.8359375 + ], + [ + 0.375, + 0.84375 + ], + [ + 0.375, + 0.8515625 + ], + [ + 0.3828125, + 0.859375 + ], + [ + 0.3828125, + 0.8671875 + ], + [ + 0.390625, + 0.875 + ], + [ + 0.390625, + 0.8828125 + ], + [ + 0.3984375, + 0.890625 + ], + [ + 0.3984375, + 0.8984375 + ], + [ + 0.40625, + 0.90625 + ], + [ + 0.40625, + 0.9140625 + ], + [ + 0.4140625, + 0.921875 + ], + [ + 0.4140625, + 0.9296875 + ], + [ + 0.421875, + 0.9375 + ], + [ + 0.421875, + 0.9453125 + ], + [ + 0.4296875, + 0.953125 + ], + [ + 0.4296875, + 0.9609375 + ], + [ + 0.4375, + 0.96875 + ], + [ + 0.4375, + 0.9765625 + ], + [ + 0.4453125, + 0.9765625 + ], + [ + 0.4453125, + 0.96875 + ], + [ + 0.453125, + 0.9609375 + ], + [ + 0.453125, + 0.953125 + ], + [ + 0.4609375, + 0.9453125 + ], + [ + 0.4609375, + 0.9375 + ], + [ + 0.46875, + 0.9296875 + ], + [ + 0.46875, + 0.921875 + ], + [ + 0.4765625, + 0.9140625 + ], + [ + 0.4765625, + 0.90625 + ], + [ + 0.4765625, + 0.8984375 + ], + [ + 0.484375, + 0.890625 + ], + [ + 0.484375, + 0.8828125 + ], + [ + 0.4921875, + 0.875 + ], + [ + 0.4921875, + 0.8671875 + ], + [ + 0.5, + 0.859375 + ], + [ + 0.5, + 0.8515625 + ], + [ + 0.5078125, + 0.84375 + ], + [ + 0.5078125, + 0.8359375 + ], + [ + 0.515625, + 0.828125 + ], + [ + 0.515625, + 0.8203125 + ], + [ + 0.515625, + 0.8125 + ], + [ + 0.5234375, + 0.8046875 + ], + [ + 0.5234375, + 0.796875 + ], + [ + 0.53125, + 0.7890625 + ], + [ + 0.53125, + 0.78125 + ], + [ + 0.5390625, + 0.7734375 + ], + [ + 0.5390625, + 0.765625 + ], + [ + 0.546875, + 0.7578125 + ], + [ + 0.546875, + 0.75 + ], + [ + 0.5546875, + 0.7421875 + ], + [ + 0.5546875, + 0.734375 + ], + [ + 0.5546875, + 0.7265625 + ], + [ + 0.5625, + 0.71875 + ], + [ + 0.5703125, + 0.71875 + ], + [ + 0.578125, + 0.71875 + ], + [ + 0.5859375, + 0.71875 + ], + [ + 0.59375, + 0.71875 + ], + [ + 0.6015625, + 0.71875 + ], + [ + 0.609375, + 0.71875 + ], + [ + 0.6171875, + 0.71875 + ], + [ + 0.625, + 0.7109375 + ], + [ + 0.6328125, + 0.7109375 + ], + [ + 0.640625, + 0.7109375 + ], + [ + 0.6484375, + 0.7109375 + ], + [ + 0.65625, + 0.7109375 + ], + [ + 0.6640625, + 0.7109375 + ], + [ + 0.671875, + 0.7109375 + ], + [ + 0.6796875, + 0.703125 + ], + [ + 0.6875, + 0.703125 + ], + [ + 0.6953125, + 0.703125 + ], + [ + 0.703125, + 0.703125 + ], + [ + 0.7109375, + 0.703125 + ], + [ + 0.71875, + 0.703125 + ], + [ + 0.7265625, + 0.703125 + ], + [ + 0.734375, + 0.703125 + ], + [ + 0.7421875, + 0.6953125 + ], + [ + 0.75, + 0.6953125 + ], + [ + 0.7578125, + 0.6953125 + ], + [ + 0.765625, + 0.6953125 + ], + [ + 0.7734375, + 0.6953125 + ], + [ + 0.78125, + 0.6953125 + ], + [ + 0.7890625, + 0.6953125 + ], + [ + 0.796875, + 0.6875 + ], + [ + 0.8046875, + 0.6875 + ], + [ + 0.8125, + 0.6875 + ], + [ + 0.8203125, + 0.6875 + ], + [ + 0.828125, + 0.6875 + ], + [ + 0.8359375, + 0.6875 + ], + [ + 0.84375, + 0.6875 + ], + [ + 0.8359375, + 0.6796875 + ], + [ + 0.828125, + 0.671875 + ], + [ + 0.8203125, + 0.6640625 + ], + [ + 0.8125, + 0.65625 + ], + [ + 0.8046875, + 0.6484375 + ], + [ + 0.796875, + 0.640625 + ], + [ + 0.7890625, + 0.6328125 + ], + [ + 0.78125, + 0.625 + ], + [ + 0.7734375, + 0.6171875 + ], + [ + 0.765625, + 0.609375 + ], + [ + 0.7578125, + 0.6015625 + ], + [ + 0.75, + 0.59375 + ], + [ + 0.7421875, + 0.59375 + ], + [ + 0.734375, + 0.5859375 + ], + [ + 0.7265625, + 0.578125 + ], + [ + 0.71875, + 0.5703125 + ], + [ + 0.7109375, + 0.5625 + ], + [ + 0.703125, + 0.5546875 + ], + [ + 0.6953125, + 0.546875 + ], + [ + 0.6875, + 0.5390625 + ], + [ + 0.6796875, + 0.53125 + ], + [ + 0.671875, + 0.5234375 + ], + [ + 0.6640625, + 0.515625 + ], + [ + 0.65625, + 0.5078125 + ], + [ + 0.6640625, + 0.5 + ], + [ + 0.671875, + 0.5 + ], + [ + 0.6640625, + 0.4921875 + ], + [ + 0.65625, + 0.484375 + ], + [ + 0.6484375, + 0.4765625 + ], + [ + 0.640625, + 0.46875 + ], + [ + 0.640625, + 0.4609375 + ], + [ + 0.6484375, + 0.453125 + ], + [ + 0.6484375, + 0.4453125 + ], + [ + 0.6484375, + 0.4375 + ], + [ + 0.6484375, + 0.4296875 + ], + [ + 0.6484375, + 0.421875 + ], + [ + 0.65625, + 0.4140625 + ], + [ + 0.65625, + 0.40625 + ], + [ + 0.65625, + 0.3984375 + ], + [ + 0.65625, + 0.390625 + ], + [ + 0.65625, + 0.3828125 + ], + [ + 0.6640625, + 0.375 + ], + [ + 0.6640625, + 0.3671875 + ], + [ + 0.6640625, + 0.359375 + ], + [ + 0.6640625, + 0.3515625 + ], + [ + 0.6640625, + 0.34375 + ], + [ + 0.671875, + 0.3359375 + ], + [ + 0.671875, + 0.328125 + ], + [ + 0.671875, + 0.3203125 + ], + [ + 0.671875, + 0.3125 + ], + [ + 0.671875, + 0.3046875 + ], + [ + 0.6796875, + 0.296875 + ], + [ + 0.6796875, + 0.2890625 + ], + [ + 0.6796875, + 0.28125 + ], + [ + 0.6796875, + 0.2734375 + ], + [ + 0.6796875, + 0.265625 + ], + [ + 0.6875, + 0.2578125 + ], + [ + 0.6875, + 0.25 + ], + [ + 0.6875, + 0.2421875 + ], + [ + 0.6875, + 0.234375 + ], + [ + 0.6875, + 0.2265625 + ], + [ + 0.6796875, + 0.21875 + ], + [ + 0.6796875, + 0.2109375 + ], + [ + 0.671875, + 0.21875 + ], + [ + 0.6640625, + 0.21875 + ], + [ + 0.65625, + 0.2265625 + ], + [ + 0.6484375, + 0.2265625 + ], + [ + 0.640625, + 0.234375 + ], + [ + 0.6328125, + 0.234375 + ], + [ + 0.625, + 0.2421875 + ], + [ + 0.6171875, + 0.2421875 + ], + [ + 0.609375, + 0.25 + ], + [ + 0.6015625, + 0.25 + ], + [ + 0.59375, + 0.2578125 + ], + [ + 0.5859375, + 0.2578125 + ], + [ + 0.578125, + 0.265625 + ], + [ + 0.5703125, + 0.265625 + ], + [ + 0.5625, + 0.2578125 + ], + [ + 0.5625, + 0.25 + ], + [ + 0.5625, + 0.2421875 + ], + [ + 0.5625, + 0.234375 + ], + [ + 0.5703125, + 0.2265625 + ], + [ + 0.5703125, + 0.21875 + ], + [ + 0.5703125, + 0.2109375 + ], + [ + 0.5703125, + 0.203125 + ], + [ + 0.5703125, + 0.1953125 + ], + [ + 0.5625, + 0.203125 + ], + [ + 0.5546875, + 0.203125 + ], + [ + 0.546875, + 0.2109375 + ], + [ + 0.5390625, + 0.2109375 + ], + [ + 0.53125, + 0.21875 + ], + [ + 0.5234375, + 0.21875 + ], + [ + 0.515625, + 0.2265625 + ], + [ + 0.5078125, + 0.2265625 + ], + [ + 0.5, + 0.234375 + ], + [ + 0.4921875, + 0.234375 + ], + [ + 0.484375, + 0.2421875 + ], + [ + 0.4765625, + 0.2421875 + ], + [ + 0.46875, + 0.25 + ], + [ + 0.4609375, + 0.25 + ], + [ + 0.453125, + 0.2578125 + ], + [ + 0.4453125, + 0.2578125 + ], + [ + 0.4375, + 0.265625 + ], + [ + 0.4296875, + 0.265625 + ], + [ + 0.421875, + 0.2734375 + ], + [ + 0.4140625, + 0.2734375 + ], + [ + 0.40625, + 0.2734375 + ], + [ + 0.3984375, + 0.265625 + ], + [ + 0.390625, + 0.265625 + ], + [ + 0.3828125, + 0.2578125 + ], + [ + 0.375, + 0.2578125 + ], + [ + 0.3671875, + 0.25 + ], + [ + 0.359375, + 0.25 + ], + [ + 0.3515625, + 0.2421875 + ], + [ + 0.34375, + 0.2421875 + ], + [ + 0.3359375, + 0.234375 + ], + [ + 0.328125, + 0.234375 + ], + [ + 0.3203125, + 0.2265625 + ], + [ + 0.3125, + 0.2265625 + ], + [ + 0.3046875, + 0.21875 + ], + [ + 0.296875, + 0.21875 + ], + [ + 0.2890625, + 0.2109375 + ], + [ + 0.28125, + 0.2109375 + ], + [ + 0.2734375, + 0.203125 + ], + [ + 0.265625, + 0.203125 + ] + ] + ], + "8": [ + [ + [ + 0.140625, + 0.0703125 + ], + [ + 0.140625, + 0.078125 + ], + [ + 0.140625, + 0.0859375 + ], + [ + 0.140625, + 0.09375 + ], + [ + 0.140625, + 0.1015625 + ], + [ + 0.1484375, + 0.109375 + ], + [ + 0.1484375, + 0.1171875 + ], + [ + 0.1484375, + 0.125 + ], + [ + 0.1484375, + 0.1328125 + ], + [ + 0.1484375, + 0.140625 + ], + [ + 0.15625, + 0.1484375 + ], + [ + 0.15625, + 0.15625 + ], + [ + 0.15625, + 0.1640625 + ], + [ + 0.15625, + 0.171875 + ], + [ + 0.15625, + 0.1796875 + ], + [ + 0.15625, + 0.1875 + ], + [ + 0.1640625, + 0.1953125 + ], + [ + 0.1640625, + 0.203125 + ], + [ + 0.1640625, + 0.2109375 + ], + [ + 0.1640625, + 0.21875 + ], + [ + 0.1640625, + 0.2265625 + ], + [ + 0.171875, + 0.234375 + ], + [ + 0.171875, + 0.2421875 + ], + [ + 0.171875, + 0.25 + ], + [ + 0.171875, + 0.2578125 + ], + [ + 0.171875, + 0.265625 + ], + [ + 0.171875, + 0.2734375 + ], + [ + 0.1640625, + 0.28125 + ], + [ + 0.15625, + 0.2890625 + ], + [ + 0.1484375, + 0.296875 + ], + [ + 0.140625, + 0.3046875 + ], + [ + 0.1328125, + 0.3125 + ], + [ + 0.125, + 0.3203125 + ], + [ + 0.1171875, + 0.328125 + ], + [ + 0.109375, + 0.3359375 + ], + [ + 0.1015625, + 0.34375 + ], + [ + 0.09375, + 0.3515625 + ], + [ + 0.0859375, + 0.359375 + ], + [ + 0.078125, + 0.3671875 + ], + [ + 0.0703125, + 0.375 + ], + [ + 0.0625, + 0.3828125 + ], + [ + 0.0546875, + 0.390625 + ], + [ + 0.046875, + 0.3984375 + ], + [ + 0.0390625, + 0.40625 + ], + [ + 0.03125, + 0.4140625 + ], + [ + 0.0390625, + 0.4140625 + ], + [ + 0.046875, + 0.4140625 + ], + [ + 0.0546875, + 0.4140625 + ], + [ + 0.0625, + 0.4140625 + ], + [ + 0.0703125, + 0.4140625 + ], + [ + 0.078125, + 0.421875 + ], + [ + 0.0859375, + 0.421875 + ], + [ + 0.09375, + 0.421875 + ], + [ + 0.1015625, + 0.421875 + ], + [ + 0.109375, + 0.421875 + ], + [ + 0.1171875, + 0.421875 + ], + [ + 0.125, + 0.421875 + ], + [ + 0.1328125, + 0.4296875 + ], + [ + 0.140625, + 0.4296875 + ], + [ + 0.1484375, + 0.4296875 + ], + [ + 0.15625, + 0.4296875 + ], + [ + 0.1640625, + 0.4296875 + ], + [ + 0.171875, + 0.4296875 + ], + [ + 0.1796875, + 0.4296875 + ], + [ + 0.1875, + 0.4375 + ], + [ + 0.1953125, + 0.4375 + ], + [ + 0.203125, + 0.4375 + ], + [ + 0.2109375, + 0.4375 + ], + [ + 0.21875, + 0.4375 + ], + [ + 0.2265625, + 0.4375 + ], + [ + 0.234375, + 0.4375 + ], + [ + 0.2421875, + 0.4453125 + ], + [ + 0.2421875, + 0.453125 + ], + [ + 0.2421875, + 0.4609375 + ], + [ + 0.25, + 0.46875 + ], + [ + 0.25, + 0.4765625 + ], + [ + 0.2578125, + 0.484375 + ], + [ + 0.2578125, + 0.4921875 + ], + [ + 0.265625, + 0.5 + ], + [ + 0.265625, + 0.5078125 + ], + [ + 0.2734375, + 0.515625 + ], + [ + 0.2734375, + 0.5234375 + ], + [ + 0.28125, + 0.53125 + ], + [ + 0.28125, + 0.5390625 + ], + [ + 0.28125, + 0.546875 + ], + [ + 0.2890625, + 0.5546875 + ], + [ + 0.2890625, + 0.5625 + ], + [ + 0.296875, + 0.5703125 + ], + [ + 0.296875, + 0.578125 + ], + [ + 0.3046875, + 0.5859375 + ], + [ + 0.3046875, + 0.59375 + ], + [ + 0.3125, + 0.6015625 + ], + [ + 0.3125, + 0.609375 + ], + [ + 0.3125, + 0.6171875 + ], + [ + 0.3125, + 0.625 + ], + [ + 0.3125, + 0.6328125 + ], + [ + 0.3125, + 0.640625 + ], + [ + 0.3125, + 0.6484375 + ], + [ + 0.3046875, + 0.65625 + ], + [ + 0.296875, + 0.6640625 + ], + [ + 0.2890625, + 0.671875 + ], + [ + 0.28125, + 0.6796875 + ], + [ + 0.2734375, + 0.6875 + ], + [ + 0.265625, + 0.6953125 + ], + [ + 0.2578125, + 0.703125 + ], + [ + 0.25, + 0.7109375 + ], + [ + 0.2421875, + 0.71875 + ], + [ + 0.234375, + 0.71875 + ], + [ + 0.2265625, + 0.7265625 + ], + [ + 0.21875, + 0.734375 + ], + [ + 0.2109375, + 0.7421875 + ], + [ + 0.203125, + 0.75 + ], + [ + 0.1953125, + 0.7578125 + ], + [ + 0.1875, + 0.765625 + ], + [ + 0.1796875, + 0.7734375 + ], + [ + 0.171875, + 0.78125 + ], + [ + 0.1796875, + 0.78125 + ], + [ + 0.1875, + 0.78125 + ], + [ + 0.1953125, + 0.78125 + ], + [ + 0.203125, + 0.78125 + ], + [ + 0.2109375, + 0.78125 + ], + [ + 0.21875, + 0.78125 + ], + [ + 0.2265625, + 0.78125 + ], + [ + 0.234375, + 0.7890625 + ], + [ + 0.2421875, + 0.7890625 + ], + [ + 0.25, + 0.7890625 + ], + [ + 0.2578125, + 0.7890625 + ], + [ + 0.265625, + 0.7890625 + ], + [ + 0.2734375, + 0.7890625 + ], + [ + 0.28125, + 0.7890625 + ], + [ + 0.2890625, + 0.7890625 + ], + [ + 0.296875, + 0.7890625 + ], + [ + 0.3046875, + 0.796875 + ], + [ + 0.3125, + 0.796875 + ], + [ + 0.3203125, + 0.796875 + ], + [ + 0.328125, + 0.796875 + ], + [ + 0.3359375, + 0.796875 + ], + [ + 0.34375, + 0.796875 + ], + [ + 0.3515625, + 0.796875 + ], + [ + 0.359375, + 0.796875 + ], + [ + 0.3671875, + 0.796875 + ], + [ + 0.375, + 0.8046875 + ], + [ + 0.375, + 0.8125 + ], + [ + 0.375, + 0.8203125 + ], + [ + 0.3828125, + 0.828125 + ], + [ + 0.3828125, + 0.8359375 + ], + [ + 0.390625, + 0.84375 + ], + [ + 0.390625, + 0.8515625 + ], + [ + 0.3984375, + 0.859375 + ], + [ + 0.3984375, + 0.8671875 + ], + [ + 0.40625, + 0.875 + ], + [ + 0.40625, + 0.8828125 + ], + [ + 0.4140625, + 0.890625 + ], + [ + 0.4140625, + 0.8984375 + ], + [ + 0.421875, + 0.90625 + ], + [ + 0.421875, + 0.9140625 + ], + [ + 0.4296875, + 0.921875 + ], + [ + 0.4296875, + 0.9296875 + ], + [ + 0.4375, + 0.9375 + ], + [ + 0.4375, + 0.9453125 + ], + [ + 0.4453125, + 0.953125 + ], + [ + 0.4453125, + 0.9609375 + ], + [ + 0.453125, + 0.96875 + ], + [ + 0.453125, + 0.9765625 + ], + [ + 0.453125, + 0.96875 + ], + [ + 0.4609375, + 0.9609375 + ], + [ + 0.4609375, + 0.953125 + ], + [ + 0.46875, + 0.9453125 + ], + [ + 0.46875, + 0.9375 + ], + [ + 0.4765625, + 0.9296875 + ], + [ + 0.4765625, + 0.921875 + ], + [ + 0.484375, + 0.9140625 + ], + [ + 0.484375, + 0.90625 + ], + [ + 0.4921875, + 0.8984375 + ], + [ + 0.4921875, + 0.890625 + ], + [ + 0.5, + 0.8828125 + ], + [ + 0.5, + 0.875 + ], + [ + 0.5078125, + 0.8671875 + ], + [ + 0.5078125, + 0.859375 + ], + [ + 0.515625, + 0.8515625 + ], + [ + 0.515625, + 0.84375 + ], + [ + 0.5234375, + 0.8359375 + ], + [ + 0.5234375, + 0.828125 + ], + [ + 0.53125, + 0.8203125 + ], + [ + 0.53125, + 0.8125 + ], + [ + 0.53125, + 0.8046875 + ], + [ + 0.5390625, + 0.796875 + ], + [ + 0.546875, + 0.796875 + ], + [ + 0.5546875, + 0.796875 + ], + [ + 0.5625, + 0.796875 + ], + [ + 0.5703125, + 0.8046875 + ], + [ + 0.5703125, + 0.8125 + ], + [ + 0.578125, + 0.8203125 + ], + [ + 0.578125, + 0.828125 + ], + [ + 0.5859375, + 0.8359375 + ], + [ + 0.5859375, + 0.84375 + ], + [ + 0.59375, + 0.8515625 + ], + [ + 0.59375, + 0.859375 + ], + [ + 0.6015625, + 0.8671875 + ], + [ + 0.6015625, + 0.875 + ], + [ + 0.609375, + 0.8828125 + ], + [ + 0.609375, + 0.890625 + ], + [ + 0.609375, + 0.8984375 + ], + [ + 0.6171875, + 0.90625 + ], + [ + 0.6171875, + 0.9140625 + ], + [ + 0.625, + 0.921875 + ], + [ + 0.625, + 0.9296875 + ], + [ + 0.6328125, + 0.9375 + ], + [ + 0.6328125, + 0.9453125 + ], + [ + 0.640625, + 0.953125 + ], + [ + 0.640625, + 0.9609375 + ], + [ + 0.6484375, + 0.96875 + ], + [ + 0.6484375, + 0.9765625 + ], + [ + 0.6484375, + 0.96875 + ], + [ + 0.65625, + 0.9609375 + ], + [ + 0.65625, + 0.953125 + ], + [ + 0.6640625, + 0.9453125 + ], + [ + 0.6640625, + 0.9375 + ], + [ + 0.671875, + 0.9296875 + ], + [ + 0.671875, + 0.921875 + ], + [ + 0.6796875, + 0.9140625 + ], + [ + 0.6796875, + 0.90625 + ], + [ + 0.6875, + 0.8984375 + ], + [ + 0.6875, + 0.890625 + ], + [ + 0.6875, + 0.8828125 + ], + [ + 0.6953125, + 0.875 + ], + [ + 0.6953125, + 0.8671875 + ], + [ + 0.703125, + 0.859375 + ], + [ + 0.703125, + 0.8515625 + ], + [ + 0.7109375, + 0.84375 + ], + [ + 0.7109375, + 0.8359375 + ], + [ + 0.71875, + 0.828125 + ], + [ + 0.71875, + 0.8203125 + ], + [ + 0.7265625, + 0.8125 + ], + [ + 0.7265625, + 0.8046875 + ], + [ + 0.734375, + 0.796875 + ], + [ + 0.734375, + 0.7890625 + ], + [ + 0.734375, + 0.78125 + ], + [ + 0.7421875, + 0.7734375 + ], + [ + 0.75, + 0.7734375 + ], + [ + 0.7578125, + 0.7734375 + ], + [ + 0.765625, + 0.7734375 + ], + [ + 0.7734375, + 0.7734375 + ], + [ + 0.78125, + 0.7734375 + ], + [ + 0.7890625, + 0.7734375 + ], + [ + 0.796875, + 0.7734375 + ], + [ + 0.8046875, + 0.765625 + ], + [ + 0.8125, + 0.765625 + ], + [ + 0.8203125, + 0.765625 + ], + [ + 0.828125, + 0.765625 + ], + [ + 0.8359375, + 0.765625 + ], + [ + 0.84375, + 0.765625 + ], + [ + 0.8515625, + 0.765625 + ], + [ + 0.859375, + 0.7578125 + ], + [ + 0.8671875, + 0.7578125 + ], + [ + 0.875, + 0.7578125 + ], + [ + 0.8828125, + 0.7578125 + ], + [ + 0.890625, + 0.7578125 + ], + [ + 0.8984375, + 0.7578125 + ], + [ + 0.90625, + 0.7578125 + ], + [ + 0.9140625, + 0.75 + ], + [ + 0.921875, + 0.75 + ], + [ + 0.9296875, + 0.75 + ], + [ + 0.9375, + 0.75 + ], + [ + 0.9453125, + 0.75 + ], + [ + 0.953125, + 0.75 + ], + [ + 0.9609375, + 0.75 + ], + [ + 0.953125, + 0.7421875 + ], + [ + 0.9453125, + 0.734375 + ], + [ + 0.9375, + 0.7265625 + ], + [ + 0.9296875, + 0.71875 + ], + [ + 0.921875, + 0.7109375 + ], + [ + 0.9140625, + 0.703125 + ], + [ + 0.90625, + 0.6953125 + ], + [ + 0.8984375, + 0.6875 + ], + [ + 0.890625, + 0.6796875 + ], + [ + 0.8828125, + 0.6796875 + ], + [ + 0.875, + 0.671875 + ], + [ + 0.8671875, + 0.6640625 + ], + [ + 0.859375, + 0.65625 + ], + [ + 0.8515625, + 0.6484375 + ], + [ + 0.84375, + 0.640625 + ], + [ + 0.8359375, + 0.6328125 + ], + [ + 0.828125, + 0.625 + ], + [ + 0.8203125, + 0.6171875 + ], + [ + 0.8125, + 0.609375 + ], + [ + 0.8046875, + 0.6015625 + ], + [ + 0.8046875, + 0.59375 + ], + [ + 0.8046875, + 0.5859375 + ], + [ + 0.8046875, + 0.578125 + ], + [ + 0.8046875, + 0.5703125 + ], + [ + 0.8046875, + 0.5625 + ], + [ + 0.8125, + 0.5546875 + ], + [ + 0.8125, + 0.546875 + ], + [ + 0.8125, + 0.5390625 + ], + [ + 0.8125, + 0.53125 + ], + [ + 0.8125, + 0.5234375 + ], + [ + 0.8125, + 0.515625 + ], + [ + 0.8203125, + 0.5078125 + ], + [ + 0.8203125, + 0.5 + ], + [ + 0.8203125, + 0.4921875 + ], + [ + 0.8203125, + 0.484375 + ], + [ + 0.8203125, + 0.4765625 + ], + [ + 0.8203125, + 0.46875 + ], + [ + 0.828125, + 0.4609375 + ], + [ + 0.828125, + 0.453125 + ], + [ + 0.828125, + 0.4453125 + ], + [ + 0.828125, + 0.4375 + ], + [ + 0.828125, + 0.4296875 + ], + [ + 0.828125, + 0.421875 + ], + [ + 0.8359375, + 0.4140625 + ], + [ + 0.8359375, + 0.40625 + ], + [ + 0.8359375, + 0.3984375 + ], + [ + 0.8359375, + 0.390625 + ], + [ + 0.8359375, + 0.3828125 + ], + [ + 0.828125, + 0.390625 + ], + [ + 0.8203125, + 0.390625 + ], + [ + 0.8125, + 0.3984375 + ], + [ + 0.8046875, + 0.3984375 + ], + [ + 0.796875, + 0.40625 + ], + [ + 0.7890625, + 0.40625 + ], + [ + 0.78125, + 0.4140625 + ], + [ + 0.7734375, + 0.4140625 + ], + [ + 0.765625, + 0.421875 + ], + [ + 0.7578125, + 0.421875 + ], + [ + 0.75, + 0.4296875 + ], + [ + 0.7421875, + 0.4296875 + ], + [ + 0.734375, + 0.4375 + ], + [ + 0.7265625, + 0.4375 + ], + [ + 0.71875, + 0.4453125 + ], + [ + 0.7109375, + 0.4453125 + ], + [ + 0.703125, + 0.453125 + ], + [ + 0.6953125, + 0.453125 + ], + [ + 0.6875, + 0.4609375 + ], + [ + 0.6796875, + 0.4609375 + ], + [ + 0.671875, + 0.46875 + ], + [ + 0.6640625, + 0.46875 + ], + [ + 0.65625, + 0.4765625 + ], + [ + 0.6484375, + 0.4765625 + ], + [ + 0.640625, + 0.4765625 + ], + [ + 0.6328125, + 0.46875 + ], + [ + 0.625, + 0.46875 + ], + [ + 0.6171875, + 0.4609375 + ], + [ + 0.6171875, + 0.453125 + ], + [ + 0.609375, + 0.4609375 + ], + [ + 0.6015625, + 0.453125 + ], + [ + 0.59375, + 0.453125 + ], + [ + 0.5859375, + 0.4453125 + ], + [ + 0.578125, + 0.4453125 + ], + [ + 0.5703125, + 0.4375 + ], + [ + 0.5625, + 0.4375 + ], + [ + 0.5546875, + 0.4296875 + ], + [ + 0.5625, + 0.421875 + ], + [ + 0.5703125, + 0.4140625 + ], + [ + 0.578125, + 0.4140625 + ], + [ + 0.5859375, + 0.4140625 + ], + [ + 0.59375, + 0.4140625 + ], + [ + 0.6015625, + 0.4140625 + ], + [ + 0.609375, + 0.4140625 + ], + [ + 0.6015625, + 0.40625 + ], + [ + 0.59375, + 0.3984375 + ], + [ + 0.5859375, + 0.390625 + ], + [ + 0.578125, + 0.3828125 + ], + [ + 0.5703125, + 0.375 + ], + [ + 0.5625, + 0.3671875 + ], + [ + 0.5546875, + 0.359375 + ], + [ + 0.546875, + 0.3515625 + ], + [ + 0.5390625, + 0.34375 + ], + [ + 0.53125, + 0.3359375 + ], + [ + 0.5234375, + 0.328125 + ], + [ + 0.515625, + 0.3203125 + ], + [ + 0.5078125, + 0.3125 + ], + [ + 0.5, + 0.3046875 + ], + [ + 0.4921875, + 0.296875 + ], + [ + 0.484375, + 0.2890625 + ], + [ + 0.4765625, + 0.28125 + ], + [ + 0.46875, + 0.2734375 + ], + [ + 0.46875, + 0.265625 + ], + [ + 0.46875, + 0.2578125 + ], + [ + 0.46875, + 0.25 + ], + [ + 0.46875, + 0.2421875 + ], + [ + 0.46875, + 0.234375 + ], + [ + 0.4765625, + 0.2265625 + ], + [ + 0.4765625, + 0.21875 + ], + [ + 0.4765625, + 0.2109375 + ], + [ + 0.4765625, + 0.203125 + ], + [ + 0.4765625, + 0.1953125 + ], + [ + 0.484375, + 0.1875 + ], + [ + 0.484375, + 0.1796875 + ], + [ + 0.484375, + 0.171875 + ], + [ + 0.484375, + 0.1640625 + ], + [ + 0.484375, + 0.15625 + ], + [ + 0.484375, + 0.1484375 + ], + [ + 0.4921875, + 0.140625 + ], + [ + 0.4921875, + 0.1328125 + ], + [ + 0.4921875, + 0.125 + ], + [ + 0.4921875, + 0.1171875 + ], + [ + 0.4921875, + 0.109375 + ], + [ + 0.5, + 0.1015625 + ], + [ + 0.5, + 0.09375 + ], + [ + 0.5, + 0.0859375 + ], + [ + 0.5, + 0.078125 + ], + [ + 0.5, + 0.0703125 + ], + [ + 0.4921875, + 0.078125 + ], + [ + 0.484375, + 0.078125 + ], + [ + 0.4765625, + 0.0859375 + ], + [ + 0.46875, + 0.0859375 + ], + [ + 0.4609375, + 0.09375 + ], + [ + 0.453125, + 0.09375 + ], + [ + 0.4453125, + 0.1015625 + ], + [ + 0.4375, + 0.1015625 + ], + [ + 0.4296875, + 0.109375 + ], + [ + 0.421875, + 0.109375 + ], + [ + 0.4140625, + 0.1171875 + ], + [ + 0.40625, + 0.125 + ], + [ + 0.3984375, + 0.125 + ], + [ + 0.390625, + 0.1328125 + ], + [ + 0.3828125, + 0.1328125 + ], + [ + 0.375, + 0.140625 + ], + [ + 0.3671875, + 0.140625 + ], + [ + 0.359375, + 0.1484375 + ], + [ + 0.3515625, + 0.1484375 + ], + [ + 0.34375, + 0.15625 + ], + [ + 0.3359375, + 0.15625 + ], + [ + 0.328125, + 0.1640625 + ], + [ + 0.3203125, + 0.1640625 + ], + [ + 0.3125, + 0.1640625 + ], + [ + 0.3046875, + 0.15625 + ], + [ + 0.296875, + 0.15625 + ], + [ + 0.2890625, + 0.1484375 + ], + [ + 0.28125, + 0.1484375 + ], + [ + 0.2734375, + 0.140625 + ], + [ + 0.265625, + 0.140625 + ], + [ + 0.2578125, + 0.1328125 + ], + [ + 0.25, + 0.1328125 + ], + [ + 0.2421875, + 0.125 + ], + [ + 0.234375, + 0.125 + ], + [ + 0.2265625, + 0.1171875 + ], + [ + 0.21875, + 0.109375 + ], + [ + 0.2109375, + 0.109375 + ], + [ + 0.203125, + 0.1015625 + ], + [ + 0.1953125, + 0.1015625 + ], + [ + 0.1875, + 0.09375 + ], + [ + 0.1796875, + 0.09375 + ], + [ + 0.171875, + 0.0859375 + ], + [ + 0.1640625, + 0.0859375 + ], + [ + 0.15625, + 0.078125 + ], + [ + 0.1484375, + 0.078125 + ] + ], + [ + [ + 0.453125, + 0.4375 + ], + [ + 0.4609375, + 0.4296875 + ], + [ + 0.46875, + 0.4375 + ], + [ + 0.46875, + 0.4453125 + ], + [ + 0.46875, + 0.453125 + ], + [ + 0.46875, + 0.4609375 + ], + [ + 0.4765625, + 0.46875 + ], + [ + 0.4765625, + 0.4765625 + ], + [ + 0.4765625, + 0.484375 + ], + [ + 0.4765625, + 0.4921875 + ], + [ + 0.4765625, + 0.5 + ], + [ + 0.4765625, + 0.5078125 + ], + [ + 0.484375, + 0.515625 + ], + [ + 0.484375, + 0.5234375 + ], + [ + 0.4765625, + 0.53125 + ], + [ + 0.46875, + 0.53125 + ], + [ + 0.4609375, + 0.5390625 + ], + [ + 0.453125, + 0.5390625 + ], + [ + 0.4453125, + 0.5390625 + ], + [ + 0.4375, + 0.53125 + ], + [ + 0.4296875, + 0.53125 + ], + [ + 0.421875, + 0.5234375 + ], + [ + 0.4140625, + 0.5234375 + ], + [ + 0.40625, + 0.515625 + ], + [ + 0.3984375, + 0.515625 + ], + [ + 0.390625, + 0.5078125 + ], + [ + 0.3828125, + 0.5078125 + ], + [ + 0.375, + 0.5 + ], + [ + 0.3828125, + 0.4921875 + ], + [ + 0.3828125, + 0.484375 + ], + [ + 0.390625, + 0.4765625 + ], + [ + 0.390625, + 0.46875 + ], + [ + 0.3984375, + 0.4609375 + ], + [ + 0.3984375, + 0.453125 + ], + [ + 0.3984375, + 0.4453125 + ], + [ + 0.40625, + 0.4375 + ], + [ + 0.4140625, + 0.4375 + ], + [ + 0.421875, + 0.4375 + ], + [ + 0.4296875, + 0.4375 + ], + [ + 0.4375, + 0.4375 + ], + [ + 0.4453125, + 0.4375 + ] + ] + ], + "9": [ + [ + [ + 0.25, + 0.8671875 + ], + [ + 0.25, + 0.875 + ], + [ + 0.25, + 0.8828125 + ], + [ + 0.25, + 0.890625 + ], + [ + 0.2578125, + 0.8984375 + ], + [ + 0.2578125, + 0.90625 + ], + [ + 0.2578125, + 0.9140625 + ], + [ + 0.2578125, + 0.90625 + ], + [ + 0.2578125, + 0.8984375 + ], + [ + 0.265625, + 0.890625 + ], + [ + 0.265625, + 0.8828125 + ], + [ + 0.265625, + 0.875 + ], + [ + 0.265625, + 0.8671875 + ], + [ + 0.2578125, + 0.875 + ] + ], + [ + [ + 0.1953125, + 0.09375 + ], + [ + 0.1953125, + 0.1015625 + ], + [ + 0.1953125, + 0.109375 + ], + [ + 0.1953125, + 0.1171875 + ], + [ + 0.1953125, + 0.125 + ], + [ + 0.203125, + 0.1328125 + ], + [ + 0.203125, + 0.140625 + ], + [ + 0.203125, + 0.1484375 + ], + [ + 0.203125, + 0.15625 + ], + [ + 0.203125, + 0.1640625 + ], + [ + 0.2109375, + 0.171875 + ], + [ + 0.2109375, + 0.1796875 + ], + [ + 0.2109375, + 0.1875 + ], + [ + 0.2109375, + 0.1953125 + ], + [ + 0.2109375, + 0.203125 + ], + [ + 0.21875, + 0.2109375 + ], + [ + 0.21875, + 0.21875 + ], + [ + 0.21875, + 0.2265625 + ], + [ + 0.21875, + 0.234375 + ], + [ + 0.21875, + 0.2421875 + ], + [ + 0.2265625, + 0.25 + ], + [ + 0.2265625, + 0.2578125 + ], + [ + 0.2265625, + 0.265625 + ], + [ + 0.2265625, + 0.2734375 + ], + [ + 0.2265625, + 0.28125 + ], + [ + 0.234375, + 0.2890625 + ], + [ + 0.234375, + 0.296875 + ], + [ + 0.234375, + 0.3046875 + ], + [ + 0.234375, + 0.3125 + ], + [ + 0.234375, + 0.3203125 + ], + [ + 0.2421875, + 0.328125 + ], + [ + 0.2421875, + 0.3359375 + ], + [ + 0.2421875, + 0.34375 + ], + [ + 0.2421875, + 0.3515625 + ], + [ + 0.2421875, + 0.359375 + ], + [ + 0.2421875, + 0.3671875 + ], + [ + 0.234375, + 0.375 + ], + [ + 0.2265625, + 0.3828125 + ], + [ + 0.21875, + 0.390625 + ], + [ + 0.2109375, + 0.3984375 + ], + [ + 0.203125, + 0.40625 + ], + [ + 0.1953125, + 0.4140625 + ], + [ + 0.1875, + 0.421875 + ], + [ + 0.1796875, + 0.4296875 + ], + [ + 0.171875, + 0.4296875 + ], + [ + 0.1640625, + 0.4375 + ], + [ + 0.15625, + 0.4453125 + ], + [ + 0.1484375, + 0.453125 + ], + [ + 0.140625, + 0.4609375 + ], + [ + 0.1328125, + 0.46875 + ], + [ + 0.125, + 0.4765625 + ], + [ + 0.1171875, + 0.484375 + ], + [ + 0.109375, + 0.4921875 + ], + [ + 0.1015625, + 0.4921875 + ], + [ + 0.09375, + 0.5 + ], + [ + 0.0859375, + 0.5078125 + ], + [ + 0.078125, + 0.515625 + ], + [ + 0.0703125, + 0.5234375 + ], + [ + 0.0625, + 0.53125 + ], + [ + 0.0546875, + 0.5390625 + ], + [ + 0.046875, + 0.546875 + ], + [ + 0.0390625, + 0.5546875 + ], + [ + 0.046875, + 0.5546875 + ], + [ + 0.0546875, + 0.5546875 + ], + [ + 0.0625, + 0.5546875 + ], + [ + 0.0703125, + 0.5546875 + ], + [ + 0.078125, + 0.5546875 + ], + [ + 0.0859375, + 0.5546875 + ], + [ + 0.09375, + 0.5625 + ], + [ + 0.1015625, + 0.5625 + ], + [ + 0.109375, + 0.5625 + ], + [ + 0.1171875, + 0.5625 + ], + [ + 0.125, + 0.5625 + ], + [ + 0.1328125, + 0.5625 + ], + [ + 0.140625, + 0.5625 + ], + [ + 0.1484375, + 0.5703125 + ], + [ + 0.15625, + 0.5703125 + ], + [ + 0.1640625, + 0.5703125 + ], + [ + 0.171875, + 0.5703125 + ], + [ + 0.1796875, + 0.5703125 + ], + [ + 0.1875, + 0.5703125 + ], + [ + 0.1953125, + 0.5703125 + ], + [ + 0.203125, + 0.5703125 + ], + [ + 0.2109375, + 0.578125 + ], + [ + 0.21875, + 0.578125 + ], + [ + 0.2265625, + 0.578125 + ], + [ + 0.234375, + 0.578125 + ], + [ + 0.2421875, + 0.578125 + ], + [ + 0.25, + 0.578125 + ], + [ + 0.2578125, + 0.578125 + ], + [ + 0.265625, + 0.5859375 + ], + [ + 0.2734375, + 0.5859375 + ], + [ + 0.28125, + 0.5859375 + ], + [ + 0.2890625, + 0.5859375 + ], + [ + 0.296875, + 0.5859375 + ], + [ + 0.3046875, + 0.5859375 + ], + [ + 0.3125, + 0.5859375 + ], + [ + 0.3203125, + 0.5859375 + ], + [ + 0.328125, + 0.59375 + ], + [ + 0.328125, + 0.6015625 + ], + [ + 0.328125, + 0.609375 + ], + [ + 0.3359375, + 0.6171875 + ], + [ + 0.3359375, + 0.625 + ], + [ + 0.34375, + 0.6328125 + ], + [ + 0.34375, + 0.640625 + ], + [ + 0.3515625, + 0.6484375 + ], + [ + 0.3515625, + 0.65625 + ], + [ + 0.359375, + 0.6640625 + ], + [ + 0.359375, + 0.671875 + ], + [ + 0.3671875, + 0.6796875 + ], + [ + 0.3671875, + 0.6875 + ], + [ + 0.3671875, + 0.6953125 + ], + [ + 0.375, + 0.703125 + ], + [ + 0.375, + 0.7109375 + ], + [ + 0.3828125, + 0.71875 + ], + [ + 0.3828125, + 0.7265625 + ], + [ + 0.390625, + 0.734375 + ], + [ + 0.390625, + 0.7421875 + ], + [ + 0.3984375, + 0.75 + ], + [ + 0.3984375, + 0.7578125 + ], + [ + 0.40625, + 0.765625 + ], + [ + 0.40625, + 0.7734375 + ], + [ + 0.40625, + 0.78125 + ], + [ + 0.4140625, + 0.7890625 + ], + [ + 0.4140625, + 0.796875 + ], + [ + 0.421875, + 0.8046875 + ], + [ + 0.421875, + 0.8125 + ], + [ + 0.4296875, + 0.8203125 + ], + [ + 0.4296875, + 0.828125 + ], + [ + 0.4375, + 0.8359375 + ], + [ + 0.4375, + 0.84375 + ], + [ + 0.4375, + 0.8359375 + ], + [ + 0.4453125, + 0.828125 + ], + [ + 0.4453125, + 0.8203125 + ], + [ + 0.453125, + 0.8125 + ], + [ + 0.453125, + 0.8046875 + ], + [ + 0.4609375, + 0.796875 + ], + [ + 0.4609375, + 0.7890625 + ], + [ + 0.46875, + 0.78125 + ], + [ + 0.46875, + 0.7734375 + ], + [ + 0.46875, + 0.765625 + ], + [ + 0.4765625, + 0.7578125 + ], + [ + 0.4765625, + 0.75 + ], + [ + 0.484375, + 0.7421875 + ], + [ + 0.484375, + 0.734375 + ], + [ + 0.4921875, + 0.7265625 + ], + [ + 0.4921875, + 0.71875 + ], + [ + 0.5, + 0.7109375 + ], + [ + 0.5, + 0.703125 + ], + [ + 0.5078125, + 0.6953125 + ], + [ + 0.5078125, + 0.6875 + ], + [ + 0.5078125, + 0.6796875 + ], + [ + 0.515625, + 0.671875 + ], + [ + 0.515625, + 0.6640625 + ], + [ + 0.5234375, + 0.65625 + ], + [ + 0.5234375, + 0.6484375 + ], + [ + 0.53125, + 0.640625 + ], + [ + 0.53125, + 0.6328125 + ], + [ + 0.5390625, + 0.625 + ], + [ + 0.5390625, + 0.6171875 + ], + [ + 0.546875, + 0.609375 + ], + [ + 0.546875, + 0.6015625 + ], + [ + 0.546875, + 0.59375 + ], + [ + 0.5546875, + 0.5859375 + ], + [ + 0.5625, + 0.5859375 + ], + [ + 0.5703125, + 0.5859375 + ], + [ + 0.578125, + 0.5859375 + ], + [ + 0.5859375, + 0.5859375 + ], + [ + 0.59375, + 0.5859375 + ], + [ + 0.6015625, + 0.5859375 + ], + [ + 0.609375, + 0.5859375 + ], + [ + 0.6171875, + 0.578125 + ], + [ + 0.625, + 0.578125 + ], + [ + 0.6328125, + 0.578125 + ], + [ + 0.640625, + 0.578125 + ], + [ + 0.6484375, + 0.578125 + ], + [ + 0.65625, + 0.578125 + ], + [ + 0.6640625, + 0.578125 + ], + [ + 0.671875, + 0.5703125 + ], + [ + 0.6796875, + 0.5703125 + ], + [ + 0.6875, + 0.5703125 + ], + [ + 0.6953125, + 0.5703125 + ], + [ + 0.703125, + 0.5703125 + ], + [ + 0.7109375, + 0.5703125 + ], + [ + 0.71875, + 0.5703125 + ], + [ + 0.7265625, + 0.5703125 + ], + [ + 0.734375, + 0.5625 + ], + [ + 0.7421875, + 0.5625 + ], + [ + 0.75, + 0.5625 + ], + [ + 0.7578125, + 0.5625 + ], + [ + 0.765625, + 0.5625 + ], + [ + 0.7734375, + 0.5625 + ], + [ + 0.78125, + 0.5625 + ], + [ + 0.7890625, + 0.5546875 + ], + [ + 0.796875, + 0.5546875 + ], + [ + 0.8046875, + 0.5546875 + ], + [ + 0.8125, + 0.5546875 + ], + [ + 0.8203125, + 0.5546875 + ], + [ + 0.828125, + 0.5546875 + ], + [ + 0.8359375, + 0.5546875 + ], + [ + 0.828125, + 0.546875 + ], + [ + 0.8203125, + 0.5390625 + ], + [ + 0.8125, + 0.53125 + ], + [ + 0.8046875, + 0.5234375 + ], + [ + 0.796875, + 0.515625 + ], + [ + 0.7890625, + 0.5078125 + ], + [ + 0.78125, + 0.5 + ], + [ + 0.7734375, + 0.4921875 + ], + [ + 0.765625, + 0.4921875 + ], + [ + 0.7578125, + 0.484375 + ], + [ + 0.75, + 0.4765625 + ], + [ + 0.7421875, + 0.46875 + ], + [ + 0.734375, + 0.4609375 + ], + [ + 0.7265625, + 0.453125 + ], + [ + 0.71875, + 0.4453125 + ], + [ + 0.7109375, + 0.4375 + ], + [ + 0.703125, + 0.4296875 + ], + [ + 0.6953125, + 0.4296875 + ], + [ + 0.6875, + 0.421875 + ], + [ + 0.6796875, + 0.4140625 + ], + [ + 0.671875, + 0.40625 + ], + [ + 0.6640625, + 0.3984375 + ], + [ + 0.65625, + 0.390625 + ], + [ + 0.6484375, + 0.3828125 + ], + [ + 0.640625, + 0.375 + ], + [ + 0.6328125, + 0.3671875 + ], + [ + 0.6328125, + 0.359375 + ], + [ + 0.6328125, + 0.3515625 + ], + [ + 0.6328125, + 0.34375 + ], + [ + 0.6328125, + 0.3359375 + ], + [ + 0.6328125, + 0.328125 + ], + [ + 0.640625, + 0.3203125 + ], + [ + 0.640625, + 0.3125 + ], + [ + 0.640625, + 0.3046875 + ], + [ + 0.640625, + 0.296875 + ], + [ + 0.640625, + 0.2890625 + ], + [ + 0.6484375, + 0.28125 + ], + [ + 0.6484375, + 0.2734375 + ], + [ + 0.6484375, + 0.265625 + ], + [ + 0.6484375, + 0.2578125 + ], + [ + 0.6484375, + 0.25 + ], + [ + 0.65625, + 0.2421875 + ], + [ + 0.65625, + 0.234375 + ], + [ + 0.65625, + 0.2265625 + ], + [ + 0.65625, + 0.21875 + ], + [ + 0.65625, + 0.2109375 + ], + [ + 0.6640625, + 0.203125 + ], + [ + 0.6640625, + 0.1953125 + ], + [ + 0.6640625, + 0.1875 + ], + [ + 0.6640625, + 0.1796875 + ], + [ + 0.6640625, + 0.171875 + ], + [ + 0.671875, + 0.1640625 + ], + [ + 0.671875, + 0.15625 + ], + [ + 0.671875, + 0.1484375 + ], + [ + 0.671875, + 0.140625 + ], + [ + 0.671875, + 0.1328125 + ], + [ + 0.6796875, + 0.125 + ], + [ + 0.6796875, + 0.1171875 + ], + [ + 0.6796875, + 0.109375 + ], + [ + 0.6796875, + 0.1015625 + ], + [ + 0.6796875, + 0.09375 + ], + [ + 0.671875, + 0.1015625 + ], + [ + 0.6640625, + 0.1015625 + ], + [ + 0.65625, + 0.109375 + ], + [ + 0.6484375, + 0.109375 + ], + [ + 0.640625, + 0.1171875 + ], + [ + 0.6328125, + 0.1171875 + ], + [ + 0.625, + 0.125 + ], + [ + 0.6171875, + 0.125 + ], + [ + 0.609375, + 0.1328125 + ], + [ + 0.6015625, + 0.1328125 + ], + [ + 0.59375, + 0.140625 + ], + [ + 0.5859375, + 0.140625 + ], + [ + 0.578125, + 0.1484375 + ], + [ + 0.5703125, + 0.1484375 + ], + [ + 0.5625, + 0.15625 + ], + [ + 0.5546875, + 0.1640625 + ], + [ + 0.546875, + 0.1640625 + ], + [ + 0.5390625, + 0.171875 + ], + [ + 0.53125, + 0.171875 + ], + [ + 0.5234375, + 0.1796875 + ], + [ + 0.515625, + 0.1796875 + ], + [ + 0.5078125, + 0.1875 + ], + [ + 0.5, + 0.1875 + ], + [ + 0.4921875, + 0.1953125 + ], + [ + 0.484375, + 0.1953125 + ], + [ + 0.4765625, + 0.203125 + ], + [ + 0.46875, + 0.203125 + ], + [ + 0.4609375, + 0.2109375 + ], + [ + 0.453125, + 0.2109375 + ], + [ + 0.4453125, + 0.21875 + ], + [ + 0.4375, + 0.21875 + ], + [ + 0.4296875, + 0.21875 + ], + [ + 0.421875, + 0.2109375 + ], + [ + 0.4140625, + 0.2109375 + ], + [ + 0.40625, + 0.203125 + ], + [ + 0.3984375, + 0.203125 + ], + [ + 0.390625, + 0.1953125 + ], + [ + 0.3828125, + 0.1953125 + ], + [ + 0.375, + 0.1875 + ], + [ + 0.3671875, + 0.1875 + ], + [ + 0.359375, + 0.1796875 + ], + [ + 0.3515625, + 0.1796875 + ], + [ + 0.34375, + 0.171875 + ], + [ + 0.3359375, + 0.171875 + ], + [ + 0.328125, + 0.1640625 + ], + [ + 0.3203125, + 0.1640625 + ], + [ + 0.3125, + 0.15625 + ], + [ + 0.3046875, + 0.1484375 + ], + [ + 0.296875, + 0.1484375 + ], + [ + 0.2890625, + 0.140625 + ], + [ + 0.28125, + 0.140625 + ], + [ + 0.2734375, + 0.1328125 + ], + [ + 0.265625, + 0.1328125 + ], + [ + 0.2578125, + 0.125 + ], + [ + 0.25, + 0.125 + ], + [ + 0.2421875, + 0.1171875 + ], + [ + 0.234375, + 0.1171875 + ], + [ + 0.2265625, + 0.109375 + ], + [ + 0.21875, + 0.109375 + ], + [ + 0.2109375, + 0.1015625 + ], + [ + 0.203125, + 0.1015625 + ] + ] + ], + "10": [ + [ + [ + 0.0703125, + 0.15625 + ], + [ + 0.0703125, + 0.1640625 + ], + [ + 0.0703125, + 0.171875 + ], + [ + 0.0703125, + 0.1796875 + ], + [ + 0.0703125, + 0.1875 + ], + [ + 0.078125, + 0.1953125 + ], + [ + 0.078125, + 0.203125 + ], + [ + 0.078125, + 0.2109375 + ], + [ + 0.078125, + 0.21875 + ], + [ + 0.078125, + 0.2265625 + ], + [ + 0.078125, + 0.234375 + ], + [ + 0.078125, + 0.2421875 + ], + [ + 0.0703125, + 0.25 + ], + [ + 0.0625, + 0.2578125 + ], + [ + 0.0546875, + 0.265625 + ], + [ + 0.046875, + 0.2734375 + ], + [ + 0.0390625, + 0.2734375 + ], + [ + 0.03125, + 0.28125 + ], + [ + 0.0234375, + 0.2890625 + ], + [ + 0.015625, + 0.296875 + ], + [ + 0.0234375, + 0.296875 + ], + [ + 0.03125, + 0.296875 + ], + [ + 0.0390625, + 0.296875 + ], + [ + 0.046875, + 0.296875 + ], + [ + 0.0546875, + 0.296875 + ], + [ + 0.0625, + 0.3046875 + ], + [ + 0.0703125, + 0.3046875 + ], + [ + 0.078125, + 0.3046875 + ], + [ + 0.0859375, + 0.3046875 + ], + [ + 0.09375, + 0.3046875 + ], + [ + 0.1015625, + 0.3046875 + ], + [ + 0.109375, + 0.3125 + ], + [ + 0.109375, + 0.3203125 + ], + [ + 0.1171875, + 0.328125 + ], + [ + 0.1171875, + 0.3359375 + ], + [ + 0.125, + 0.34375 + ], + [ + 0.125, + 0.3515625 + ], + [ + 0.1328125, + 0.359375 + ], + [ + 0.1328125, + 0.3671875 + ], + [ + 0.140625, + 0.375 + ], + [ + 0.140625, + 0.3828125 + ], + [ + 0.140625, + 0.375 + ], + [ + 0.1484375, + 0.3671875 + ], + [ + 0.1484375, + 0.359375 + ], + [ + 0.15625, + 0.3515625 + ], + [ + 0.15625, + 0.34375 + ], + [ + 0.1640625, + 0.3359375 + ], + [ + 0.1640625, + 0.328125 + ], + [ + 0.171875, + 0.3203125 + ], + [ + 0.171875, + 0.3125 + ], + [ + 0.1796875, + 0.3046875 + ], + [ + 0.1875, + 0.3046875 + ], + [ + 0.1953125, + 0.3046875 + ], + [ + 0.203125, + 0.3046875 + ], + [ + 0.2109375, + 0.3125 + ], + [ + 0.2109375, + 0.3203125 + ], + [ + 0.2109375, + 0.328125 + ], + [ + 0.2109375, + 0.3359375 + ], + [ + 0.2109375, + 0.34375 + ], + [ + 0.21875, + 0.3515625 + ], + [ + 0.21875, + 0.359375 + ], + [ + 0.21875, + 0.3671875 + ], + [ + 0.21875, + 0.375 + ], + [ + 0.21875, + 0.3828125 + ], + [ + 0.2265625, + 0.390625 + ], + [ + 0.2265625, + 0.3984375 + ], + [ + 0.2265625, + 0.40625 + ], + [ + 0.2265625, + 0.4140625 + ], + [ + 0.2265625, + 0.421875 + ], + [ + 0.2265625, + 0.4296875 + ], + [ + 0.234375, + 0.4375 + ], + [ + 0.234375, + 0.4453125 + ], + [ + 0.234375, + 0.453125 + ], + [ + 0.234375, + 0.4609375 + ], + [ + 0.234375, + 0.46875 + ], + [ + 0.234375, + 0.4765625 + ], + [ + 0.2421875, + 0.484375 + ], + [ + 0.2421875, + 0.4921875 + ], + [ + 0.2421875, + 0.5 + ], + [ + 0.2421875, + 0.5078125 + ], + [ + 0.2421875, + 0.515625 + ], + [ + 0.2421875, + 0.5234375 + ], + [ + 0.234375, + 0.53125 + ], + [ + 0.2265625, + 0.5390625 + ], + [ + 0.21875, + 0.546875 + ], + [ + 0.2109375, + 0.5546875 + ], + [ + 0.203125, + 0.5625 + ], + [ + 0.1953125, + 0.5703125 + ], + [ + 0.1875, + 0.578125 + ], + [ + 0.1796875, + 0.5859375 + ], + [ + 0.171875, + 0.59375 + ], + [ + 0.1640625, + 0.6015625 + ], + [ + 0.15625, + 0.609375 + ], + [ + 0.1484375, + 0.6171875 + ], + [ + 0.140625, + 0.625 + ], + [ + 0.1328125, + 0.6328125 + ], + [ + 0.125, + 0.640625 + ], + [ + 0.1171875, + 0.6484375 + ], + [ + 0.109375, + 0.65625 + ], + [ + 0.1015625, + 0.6640625 + ], + [ + 0.09375, + 0.671875 + ], + [ + 0.0859375, + 0.6796875 + ], + [ + 0.078125, + 0.6875 + ], + [ + 0.0703125, + 0.6953125 + ], + [ + 0.0625, + 0.703125 + ], + [ + 0.0546875, + 0.7109375 + ], + [ + 0.0625, + 0.7109375 + ], + [ + 0.0703125, + 0.7109375 + ], + [ + 0.078125, + 0.7109375 + ], + [ + 0.0859375, + 0.7109375 + ], + [ + 0.09375, + 0.7109375 + ], + [ + 0.1015625, + 0.71875 + ], + [ + 0.109375, + 0.71875 + ], + [ + 0.1171875, + 0.71875 + ], + [ + 0.125, + 0.71875 + ], + [ + 0.1328125, + 0.71875 + ], + [ + 0.140625, + 0.71875 + ], + [ + 0.1484375, + 0.71875 + ], + [ + 0.15625, + 0.7265625 + ], + [ + 0.1640625, + 0.7265625 + ], + [ + 0.171875, + 0.7265625 + ], + [ + 0.1796875, + 0.7265625 + ], + [ + 0.1875, + 0.7265625 + ], + [ + 0.1953125, + 0.7265625 + ], + [ + 0.203125, + 0.7265625 + ], + [ + 0.2109375, + 0.734375 + ], + [ + 0.21875, + 0.734375 + ], + [ + 0.2265625, + 0.734375 + ], + [ + 0.234375, + 0.734375 + ], + [ + 0.2421875, + 0.734375 + ], + [ + 0.25, + 0.734375 + ], + [ + 0.2578125, + 0.734375 + ], + [ + 0.265625, + 0.7421875 + ], + [ + 0.2734375, + 0.7421875 + ], + [ + 0.28125, + 0.7421875 + ], + [ + 0.2890625, + 0.7421875 + ], + [ + 0.296875, + 0.7421875 + ], + [ + 0.3046875, + 0.7421875 + ], + [ + 0.3125, + 0.7421875 + ], + [ + 0.3203125, + 0.75 + ], + [ + 0.3203125, + 0.7578125 + ], + [ + 0.328125, + 0.765625 + ], + [ + 0.328125, + 0.7734375 + ], + [ + 0.3359375, + 0.78125 + ], + [ + 0.3359375, + 0.7890625 + ], + [ + 0.34375, + 0.796875 + ], + [ + 0.34375, + 0.8046875 + ], + [ + 0.3515625, + 0.8125 + ], + [ + 0.3515625, + 0.8203125 + ], + [ + 0.359375, + 0.828125 + ], + [ + 0.359375, + 0.8359375 + ], + [ + 0.3671875, + 0.84375 + ], + [ + 0.3671875, + 0.8515625 + ], + [ + 0.375, + 0.859375 + ], + [ + 0.375, + 0.8671875 + ], + [ + 0.3828125, + 0.875 + ], + [ + 0.3828125, + 0.8828125 + ], + [ + 0.390625, + 0.890625 + ], + [ + 0.390625, + 0.8984375 + ], + [ + 0.3984375, + 0.90625 + ], + [ + 0.3984375, + 0.9140625 + ], + [ + 0.40625, + 0.921875 + ], + [ + 0.40625, + 0.9296875 + ], + [ + 0.4140625, + 0.9375 + ], + [ + 0.4140625, + 0.9453125 + ], + [ + 0.421875, + 0.953125 + ], + [ + 0.421875, + 0.9609375 + ], + [ + 0.4296875, + 0.96875 + ], + [ + 0.4296875, + 0.9765625 + ], + [ + 0.4296875, + 0.96875 + ], + [ + 0.4375, + 0.9609375 + ], + [ + 0.4375, + 0.953125 + ], + [ + 0.4453125, + 0.9453125 + ], + [ + 0.4453125, + 0.9375 + ], + [ + 0.453125, + 0.9296875 + ], + [ + 0.453125, + 0.921875 + ], + [ + 0.4609375, + 0.9140625 + ], + [ + 0.4609375, + 0.90625 + ], + [ + 0.46875, + 0.8984375 + ], + [ + 0.46875, + 0.890625 + ], + [ + 0.4765625, + 0.8828125 + ], + [ + 0.4765625, + 0.875 + ], + [ + 0.484375, + 0.8671875 + ], + [ + 0.4921875, + 0.8671875 + ], + [ + 0.5, + 0.875 + ], + [ + 0.5, + 0.8828125 + ], + [ + 0.5078125, + 0.890625 + ], + [ + 0.5078125, + 0.8984375 + ], + [ + 0.515625, + 0.90625 + ], + [ + 0.515625, + 0.9140625 + ], + [ + 0.5234375, + 0.921875 + ], + [ + 0.5234375, + 0.9296875 + ], + [ + 0.53125, + 0.9375 + ], + [ + 0.53125, + 0.9453125 + ], + [ + 0.5390625, + 0.953125 + ], + [ + 0.5390625, + 0.9609375 + ], + [ + 0.546875, + 0.96875 + ], + [ + 0.546875, + 0.9765625 + ], + [ + 0.546875, + 0.96875 + ], + [ + 0.5546875, + 0.9609375 + ], + [ + 0.5546875, + 0.953125 + ], + [ + 0.5625, + 0.9453125 + ], + [ + 0.5625, + 0.9375 + ], + [ + 0.5703125, + 0.9296875 + ], + [ + 0.5703125, + 0.921875 + ], + [ + 0.578125, + 0.9140625 + ], + [ + 0.578125, + 0.90625 + ], + [ + 0.5859375, + 0.8984375 + ], + [ + 0.5859375, + 0.890625 + ], + [ + 0.59375, + 0.8828125 + ], + [ + 0.59375, + 0.875 + ], + [ + 0.6015625, + 0.8671875 + ], + [ + 0.6015625, + 0.859375 + ], + [ + 0.6015625, + 0.8515625 + ], + [ + 0.609375, + 0.84375 + ], + [ + 0.609375, + 0.8359375 + ], + [ + 0.6171875, + 0.828125 + ], + [ + 0.6171875, + 0.8203125 + ], + [ + 0.625, + 0.8125 + ], + [ + 0.625, + 0.8046875 + ], + [ + 0.6328125, + 0.796875 + ], + [ + 0.6328125, + 0.7890625 + ], + [ + 0.640625, + 0.78125 + ], + [ + 0.640625, + 0.7734375 + ], + [ + 0.6484375, + 0.765625 + ], + [ + 0.6484375, + 0.7578125 + ], + [ + 0.65625, + 0.75 + ], + [ + 0.65625, + 0.7421875 + ], + [ + 0.6640625, + 0.734375 + ], + [ + 0.671875, + 0.7265625 + ], + [ + 0.6796875, + 0.7265625 + ], + [ + 0.6875, + 0.7265625 + ], + [ + 0.6953125, + 0.7265625 + ], + [ + 0.703125, + 0.7265625 + ], + [ + 0.7109375, + 0.71875 + ], + [ + 0.71875, + 0.71875 + ], + [ + 0.7265625, + 0.71875 + ], + [ + 0.734375, + 0.71875 + ], + [ + 0.7421875, + 0.71875 + ], + [ + 0.75, + 0.71875 + ], + [ + 0.7578125, + 0.71875 + ], + [ + 0.765625, + 0.7109375 + ], + [ + 0.7734375, + 0.7109375 + ], + [ + 0.78125, + 0.7109375 + ], + [ + 0.7890625, + 0.7109375 + ], + [ + 0.796875, + 0.7109375 + ], + [ + 0.8046875, + 0.7109375 + ], + [ + 0.796875, + 0.703125 + ], + [ + 0.8046875, + 0.6953125 + ], + [ + 0.8125, + 0.6953125 + ], + [ + 0.8203125, + 0.6953125 + ], + [ + 0.828125, + 0.6953125 + ], + [ + 0.8359375, + 0.6953125 + ], + [ + 0.84375, + 0.6953125 + ], + [ + 0.8515625, + 0.6875 + ], + [ + 0.859375, + 0.6875 + ], + [ + 0.8671875, + 0.6875 + ], + [ + 0.875, + 0.6875 + ], + [ + 0.8828125, + 0.6875 + ], + [ + 0.890625, + 0.6875 + ], + [ + 0.8984375, + 0.6875 + ], + [ + 0.90625, + 0.6875 + ], + [ + 0.9140625, + 0.6796875 + ], + [ + 0.921875, + 0.6796875 + ], + [ + 0.9296875, + 0.6796875 + ], + [ + 0.9375, + 0.6796875 + ], + [ + 0.9453125, + 0.6796875 + ], + [ + 0.953125, + 0.6796875 + ], + [ + 0.9609375, + 0.6796875 + ], + [ + 0.953125, + 0.671875 + ], + [ + 0.9453125, + 0.6640625 + ], + [ + 0.9375, + 0.65625 + ], + [ + 0.9296875, + 0.6484375 + ], + [ + 0.921875, + 0.640625 + ], + [ + 0.9140625, + 0.6328125 + ], + [ + 0.90625, + 0.625 + ], + [ + 0.8984375, + 0.6171875 + ], + [ + 0.890625, + 0.6171875 + ], + [ + 0.8828125, + 0.609375 + ], + [ + 0.875, + 0.6015625 + ], + [ + 0.8671875, + 0.59375 + ], + [ + 0.859375, + 0.5859375 + ], + [ + 0.8515625, + 0.578125 + ], + [ + 0.84375, + 0.5703125 + ], + [ + 0.8359375, + 0.5625 + ], + [ + 0.828125, + 0.5546875 + ], + [ + 0.8203125, + 0.5546875 + ], + [ + 0.8125, + 0.546875 + ], + [ + 0.8046875, + 0.5390625 + ], + [ + 0.796875, + 0.53125 + ], + [ + 0.7890625, + 0.5234375 + ], + [ + 0.78125, + 0.515625 + ], + [ + 0.7734375, + 0.5078125 + ], + [ + 0.765625, + 0.5 + ], + [ + 0.7578125, + 0.4921875 + ], + [ + 0.75, + 0.484375 + ], + [ + 0.75, + 0.4765625 + ], + [ + 0.75, + 0.46875 + ], + [ + 0.75, + 0.4609375 + ], + [ + 0.75, + 0.453125 + ], + [ + 0.75, + 0.4453125 + ], + [ + 0.7578125, + 0.4375 + ], + [ + 0.7578125, + 0.4296875 + ], + [ + 0.7578125, + 0.421875 + ], + [ + 0.7578125, + 0.4140625 + ], + [ + 0.7578125, + 0.40625 + ], + [ + 0.765625, + 0.3984375 + ], + [ + 0.765625, + 0.390625 + ], + [ + 0.765625, + 0.3828125 + ], + [ + 0.765625, + 0.375 + ], + [ + 0.765625, + 0.3671875 + ], + [ + 0.765625, + 0.359375 + ], + [ + 0.7734375, + 0.3515625 + ], + [ + 0.7734375, + 0.34375 + ], + [ + 0.7734375, + 0.3359375 + ], + [ + 0.7734375, + 0.328125 + ], + [ + 0.7734375, + 0.3203125 + ], + [ + 0.78125, + 0.3125 + ], + [ + 0.78125, + 0.3046875 + ], + [ + 0.78125, + 0.296875 + ], + [ + 0.78125, + 0.2890625 + ], + [ + 0.78125, + 0.28125 + ], + [ + 0.78125, + 0.2734375 + ], + [ + 0.7890625, + 0.265625 + ], + [ + 0.7890625, + 0.2578125 + ], + [ + 0.7890625, + 0.25 + ], + [ + 0.7890625, + 0.2421875 + ], + [ + 0.7890625, + 0.234375 + ], + [ + 0.796875, + 0.2265625 + ], + [ + 0.796875, + 0.21875 + ], + [ + 0.796875, + 0.2109375 + ], + [ + 0.796875, + 0.203125 + ], + [ + 0.796875, + 0.1953125 + ], + [ + 0.7890625, + 0.203125 + ], + [ + 0.78125, + 0.203125 + ], + [ + 0.7734375, + 0.2109375 + ], + [ + 0.765625, + 0.2109375 + ], + [ + 0.7578125, + 0.21875 + ], + [ + 0.75, + 0.21875 + ], + [ + 0.7421875, + 0.2265625 + ], + [ + 0.734375, + 0.2265625 + ], + [ + 0.7265625, + 0.234375 + ], + [ + 0.71875, + 0.234375 + ], + [ + 0.7109375, + 0.2421875 + ], + [ + 0.703125, + 0.25 + ], + [ + 0.6953125, + 0.25 + ], + [ + 0.6875, + 0.2578125 + ], + [ + 0.6796875, + 0.2578125 + ], + [ + 0.671875, + 0.265625 + ], + [ + 0.6640625, + 0.265625 + ], + [ + 0.65625, + 0.265625 + ], + [ + 0.6484375, + 0.2734375 + ], + [ + 0.640625, + 0.2734375 + ], + [ + 0.6328125, + 0.28125 + ], + [ + 0.625, + 0.28125 + ], + [ + 0.6171875, + 0.2890625 + ], + [ + 0.609375, + 0.2890625 + ], + [ + 0.6015625, + 0.296875 + ], + [ + 0.59375, + 0.296875 + ], + [ + 0.5859375, + 0.3046875 + ], + [ + 0.578125, + 0.3046875 + ], + [ + 0.5703125, + 0.3125 + ], + [ + 0.5625, + 0.3125 + ], + [ + 0.5546875, + 0.3203125 + ], + [ + 0.546875, + 0.3203125 + ], + [ + 0.5390625, + 0.328125 + ], + [ + 0.53125, + 0.3203125 + ], + [ + 0.5234375, + 0.3203125 + ], + [ + 0.515625, + 0.3125 + ], + [ + 0.5078125, + 0.3125 + ], + [ + 0.5, + 0.3046875 + ], + [ + 0.4921875, + 0.3046875 + ], + [ + 0.484375, + 0.296875 + ], + [ + 0.4765625, + 0.296875 + ], + [ + 0.46875, + 0.2890625 + ], + [ + 0.4609375, + 0.28125 + ], + [ + 0.453125, + 0.28125 + ], + [ + 0.4453125, + 0.2734375 + ], + [ + 0.4375, + 0.2734375 + ], + [ + 0.4296875, + 0.265625 + ], + [ + 0.421875, + 0.265625 + ], + [ + 0.4140625, + 0.2578125 + ], + [ + 0.40625, + 0.2578125 + ], + [ + 0.3984375, + 0.25 + ], + [ + 0.390625, + 0.25 + ], + [ + 0.3828125, + 0.2421875 + ], + [ + 0.375, + 0.234375 + ], + [ + 0.3671875, + 0.234375 + ], + [ + 0.359375, + 0.2265625 + ], + [ + 0.3515625, + 0.2265625 + ], + [ + 0.34375, + 0.21875 + ], + [ + 0.3359375, + 0.21875 + ], + [ + 0.328125, + 0.2109375 + ], + [ + 0.3203125, + 0.2109375 + ], + [ + 0.3125, + 0.203125 + ], + [ + 0.3046875, + 0.203125 + ], + [ + 0.296875, + 0.1953125 + ], + [ + 0.296875, + 0.203125 + ], + [ + 0.296875, + 0.2109375 + ], + [ + 0.296875, + 0.21875 + ], + [ + 0.296875, + 0.2265625 + ], + [ + 0.3046875, + 0.234375 + ], + [ + 0.3046875, + 0.2421875 + ], + [ + 0.3046875, + 0.25 + ], + [ + 0.3046875, + 0.2578125 + ], + [ + 0.3046875, + 0.265625 + ], + [ + 0.3125, + 0.2734375 + ], + [ + 0.3125, + 0.28125 + ], + [ + 0.3125, + 0.2890625 + ], + [ + 0.3125, + 0.296875 + ], + [ + 0.3125, + 0.3046875 + ], + [ + 0.3125, + 0.3125 + ], + [ + 0.3046875, + 0.3203125 + ], + [ + 0.296875, + 0.3125 + ], + [ + 0.2890625, + 0.3125 + ], + [ + 0.28125, + 0.3046875 + ], + [ + 0.2734375, + 0.3046875 + ], + [ + 0.265625, + 0.296875 + ], + [ + 0.2578125, + 0.2890625 + ], + [ + 0.25, + 0.28125 + ], + [ + 0.2421875, + 0.2734375 + ], + [ + 0.234375, + 0.2734375 + ], + [ + 0.2265625, + 0.265625 + ], + [ + 0.21875, + 0.2578125 + ], + [ + 0.2109375, + 0.25 + ], + [ + 0.203125, + 0.2421875 + ], + [ + 0.203125, + 0.234375 + ], + [ + 0.203125, + 0.2265625 + ], + [ + 0.203125, + 0.21875 + ], + [ + 0.203125, + 0.2109375 + ], + [ + 0.203125, + 0.203125 + ], + [ + 0.203125, + 0.1953125 + ], + [ + 0.2109375, + 0.1875 + ], + [ + 0.2109375, + 0.1796875 + ], + [ + 0.2109375, + 0.171875 + ], + [ + 0.2109375, + 0.1640625 + ], + [ + 0.2109375, + 0.15625 + ], + [ + 0.203125, + 0.15625 + ], + [ + 0.1953125, + 0.1640625 + ], + [ + 0.1875, + 0.1640625 + ], + [ + 0.1796875, + 0.171875 + ], + [ + 0.171875, + 0.171875 + ], + [ + 0.1640625, + 0.1796875 + ], + [ + 0.15625, + 0.1796875 + ], + [ + 0.1484375, + 0.1875 + ], + [ + 0.140625, + 0.1875 + ], + [ + 0.1328125, + 0.1875 + ], + [ + 0.125, + 0.1796875 + ], + [ + 0.1171875, + 0.1796875 + ], + [ + 0.109375, + 0.171875 + ], + [ + 0.1015625, + 0.171875 + ], + [ + 0.09375, + 0.1640625 + ], + [ + 0.0859375, + 0.1640625 + ], + [ + 0.078125, + 0.15625 + ] + ] + ], + "11": [ + [ + [ + 0.34375, + 0.0546875 + ], + [ + 0.34375, + 0.0625 + ], + [ + 0.34375, + 0.0703125 + ], + [ + 0.34375, + 0.078125 + ], + [ + 0.34375, + 0.0859375 + ], + [ + 0.3515625, + 0.09375 + ], + [ + 0.3515625, + 0.1015625 + ], + [ + 0.3515625, + 0.109375 + ], + [ + 0.3515625, + 0.1171875 + ], + [ + 0.3515625, + 0.125 + ], + [ + 0.359375, + 0.1328125 + ], + [ + 0.359375, + 0.140625 + ], + [ + 0.359375, + 0.1484375 + ], + [ + 0.359375, + 0.15625 + ], + [ + 0.3515625, + 0.1640625 + ], + [ + 0.34375, + 0.15625 + ], + [ + 0.3359375, + 0.15625 + ], + [ + 0.328125, + 0.1484375 + ], + [ + 0.3203125, + 0.1484375 + ], + [ + 0.3125, + 0.140625 + ], + [ + 0.3046875, + 0.140625 + ], + [ + 0.296875, + 0.1328125 + ], + [ + 0.2890625, + 0.1328125 + ], + [ + 0.28125, + 0.125 + ], + [ + 0.2734375, + 0.125 + ], + [ + 0.265625, + 0.1171875 + ], + [ + 0.2578125, + 0.1171875 + ], + [ + 0.25, + 0.109375 + ], + [ + 0.2421875, + 0.109375 + ], + [ + 0.234375, + 0.1015625 + ], + [ + 0.234375, + 0.109375 + ], + [ + 0.234375, + 0.1171875 + ], + [ + 0.234375, + 0.125 + ], + [ + 0.234375, + 0.1328125 + ], + [ + 0.2421875, + 0.140625 + ], + [ + 0.2421875, + 0.1484375 + ], + [ + 0.2421875, + 0.15625 + ], + [ + 0.2421875, + 0.1640625 + ], + [ + 0.2421875, + 0.171875 + ], + [ + 0.2421875, + 0.1796875 + ], + [ + 0.25, + 0.1875 + ], + [ + 0.25, + 0.1953125 + ], + [ + 0.25, + 0.203125 + ], + [ + 0.25, + 0.2109375 + ], + [ + 0.25, + 0.21875 + ], + [ + 0.25, + 0.2265625 + ], + [ + 0.2578125, + 0.234375 + ], + [ + 0.2578125, + 0.2421875 + ], + [ + 0.2578125, + 0.25 + ], + [ + 0.2578125, + 0.2578125 + ], + [ + 0.2578125, + 0.265625 + ], + [ + 0.2578125, + 0.2734375 + ], + [ + 0.265625, + 0.28125 + ], + [ + 0.265625, + 0.2890625 + ], + [ + 0.265625, + 0.296875 + ], + [ + 0.265625, + 0.3046875 + ], + [ + 0.2578125, + 0.3125 + ], + [ + 0.265625, + 0.3203125 + ], + [ + 0.2734375, + 0.328125 + ], + [ + 0.2734375, + 0.3359375 + ], + [ + 0.2734375, + 0.34375 + ], + [ + 0.2734375, + 0.3515625 + ], + [ + 0.2734375, + 0.359375 + ], + [ + 0.2734375, + 0.3671875 + ], + [ + 0.28125, + 0.375 + ], + [ + 0.28125, + 0.3828125 + ], + [ + 0.28125, + 0.390625 + ], + [ + 0.28125, + 0.3984375 + ], + [ + 0.28125, + 0.40625 + ], + [ + 0.28125, + 0.4140625 + ], + [ + 0.2734375, + 0.421875 + ], + [ + 0.265625, + 0.4296875 + ], + [ + 0.2578125, + 0.4375 + ], + [ + 0.25, + 0.4453125 + ], + [ + 0.2421875, + 0.453125 + ], + [ + 0.234375, + 0.4609375 + ], + [ + 0.2265625, + 0.46875 + ], + [ + 0.21875, + 0.4765625 + ], + [ + 0.2109375, + 0.484375 + ], + [ + 0.203125, + 0.4921875 + ], + [ + 0.1953125, + 0.5 + ], + [ + 0.1875, + 0.5078125 + ], + [ + 0.1796875, + 0.515625 + ], + [ + 0.171875, + 0.5234375 + ], + [ + 0.1640625, + 0.53125 + ], + [ + 0.15625, + 0.5390625 + ], + [ + 0.1484375, + 0.546875 + ], + [ + 0.140625, + 0.5546875 + ], + [ + 0.1328125, + 0.5625 + ], + [ + 0.125, + 0.5703125 + ], + [ + 0.1171875, + 0.578125 + ], + [ + 0.109375, + 0.5859375 + ], + [ + 0.1015625, + 0.59375 + ], + [ + 0.09375, + 0.6015625 + ], + [ + 0.0859375, + 0.609375 + ], + [ + 0.078125, + 0.6171875 + ], + [ + 0.0703125, + 0.625 + ], + [ + 0.0625, + 0.6328125 + ], + [ + 0.0703125, + 0.6328125 + ], + [ + 0.078125, + 0.6328125 + ], + [ + 0.0859375, + 0.6328125 + ], + [ + 0.09375, + 0.6328125 + ], + [ + 0.1015625, + 0.6328125 + ], + [ + 0.109375, + 0.640625 + ], + [ + 0.1171875, + 0.640625 + ], + [ + 0.125, + 0.640625 + ], + [ + 0.1328125, + 0.640625 + ], + [ + 0.140625, + 0.640625 + ], + [ + 0.1484375, + 0.640625 + ], + [ + 0.15625, + 0.640625 + ], + [ + 0.1640625, + 0.6484375 + ], + [ + 0.171875, + 0.6484375 + ], + [ + 0.1796875, + 0.6484375 + ], + [ + 0.1875, + 0.6484375 + ], + [ + 0.1953125, + 0.6484375 + ], + [ + 0.203125, + 0.6484375 + ], + [ + 0.2109375, + 0.6484375 + ], + [ + 0.21875, + 0.65625 + ], + [ + 0.2265625, + 0.65625 + ], + [ + 0.234375, + 0.65625 + ], + [ + 0.2421875, + 0.65625 + ], + [ + 0.25, + 0.65625 + ], + [ + 0.2578125, + 0.65625 + ], + [ + 0.265625, + 0.6640625 + ], + [ + 0.2734375, + 0.6640625 + ], + [ + 0.28125, + 0.6640625 + ], + [ + 0.2890625, + 0.6640625 + ], + [ + 0.296875, + 0.6640625 + ], + [ + 0.3046875, + 0.6640625 + ], + [ + 0.3125, + 0.6640625 + ], + [ + 0.3203125, + 0.671875 + ], + [ + 0.328125, + 0.671875 + ], + [ + 0.3359375, + 0.671875 + ], + [ + 0.34375, + 0.671875 + ], + [ + 0.3515625, + 0.671875 + ], + [ + 0.359375, + 0.6796875 + ], + [ + 0.359375, + 0.6875 + ], + [ + 0.359375, + 0.6953125 + ], + [ + 0.359375, + 0.703125 + ], + [ + 0.3515625, + 0.7109375 + ], + [ + 0.34375, + 0.71875 + ], + [ + 0.3359375, + 0.7265625 + ], + [ + 0.328125, + 0.734375 + ], + [ + 0.3203125, + 0.7421875 + ], + [ + 0.3125, + 0.75 + ], + [ + 0.3046875, + 0.7578125 + ], + [ + 0.296875, + 0.7578125 + ], + [ + 0.2890625, + 0.765625 + ], + [ + 0.28125, + 0.7734375 + ], + [ + 0.2734375, + 0.78125 + ], + [ + 0.265625, + 0.7890625 + ], + [ + 0.2578125, + 0.796875 + ], + [ + 0.25, + 0.8046875 + ], + [ + 0.2578125, + 0.8046875 + ], + [ + 0.265625, + 0.8046875 + ], + [ + 0.2734375, + 0.8046875 + ], + [ + 0.28125, + 0.8046875 + ], + [ + 0.2890625, + 0.8046875 + ], + [ + 0.296875, + 0.8046875 + ], + [ + 0.3046875, + 0.8125 + ], + [ + 0.3125, + 0.8125 + ], + [ + 0.3203125, + 0.8125 + ], + [ + 0.328125, + 0.8125 + ], + [ + 0.3359375, + 0.8125 + ], + [ + 0.34375, + 0.8125 + ], + [ + 0.3515625, + 0.8125 + ], + [ + 0.359375, + 0.8203125 + ], + [ + 0.3671875, + 0.8203125 + ], + [ + 0.375, + 0.8203125 + ], + [ + 0.3828125, + 0.8203125 + ], + [ + 0.390625, + 0.8203125 + ], + [ + 0.3984375, + 0.8203125 + ], + [ + 0.40625, + 0.8203125 + ], + [ + 0.4140625, + 0.828125 + ], + [ + 0.4140625, + 0.8359375 + ], + [ + 0.4140625, + 0.84375 + ], + [ + 0.421875, + 0.8515625 + ], + [ + 0.421875, + 0.859375 + ], + [ + 0.4296875, + 0.8671875 + ], + [ + 0.4296875, + 0.875 + ], + [ + 0.4375, + 0.8828125 + ], + [ + 0.4375, + 0.890625 + ], + [ + 0.4453125, + 0.8984375 + ], + [ + 0.4453125, + 0.90625 + ], + [ + 0.4453125, + 0.9140625 + ], + [ + 0.453125, + 0.921875 + ], + [ + 0.453125, + 0.9296875 + ], + [ + 0.4609375, + 0.9375 + ], + [ + 0.4609375, + 0.9453125 + ], + [ + 0.46875, + 0.953125 + ], + [ + 0.46875, + 0.9609375 + ], + [ + 0.46875, + 0.953125 + ], + [ + 0.4765625, + 0.9453125 + ], + [ + 0.4765625, + 0.9375 + ], + [ + 0.484375, + 0.9296875 + ], + [ + 0.4921875, + 0.921875 + ], + [ + 0.5, + 0.9296875 + ], + [ + 0.5, + 0.9375 + ], + [ + 0.5078125, + 0.9453125 + ], + [ + 0.5078125, + 0.953125 + ], + [ + 0.5078125, + 0.9453125 + ], + [ + 0.515625, + 0.9375 + ], + [ + 0.515625, + 0.9296875 + ], + [ + 0.5234375, + 0.921875 + ], + [ + 0.5234375, + 0.9140625 + ], + [ + 0.53125, + 0.90625 + ], + [ + 0.53125, + 0.8984375 + ], + [ + 0.5390625, + 0.890625 + ], + [ + 0.5390625, + 0.8828125 + ], + [ + 0.546875, + 0.875 + ], + [ + 0.546875, + 0.8671875 + ], + [ + 0.5546875, + 0.859375 + ], + [ + 0.5546875, + 0.8515625 + ], + [ + 0.5625, + 0.84375 + ], + [ + 0.5625, + 0.8359375 + ], + [ + 0.5703125, + 0.828125 + ], + [ + 0.578125, + 0.8203125 + ], + [ + 0.5859375, + 0.8125 + ], + [ + 0.59375, + 0.8125 + ], + [ + 0.6015625, + 0.8125 + ], + [ + 0.609375, + 0.8125 + ], + [ + 0.6171875, + 0.8125 + ], + [ + 0.625, + 0.8125 + ], + [ + 0.6328125, + 0.8125 + ], + [ + 0.640625, + 0.8046875 + ], + [ + 0.6484375, + 0.8046875 + ], + [ + 0.65625, + 0.8046875 + ], + [ + 0.6640625, + 0.8046875 + ], + [ + 0.671875, + 0.8046875 + ], + [ + 0.6796875, + 0.8046875 + ], + [ + 0.6875, + 0.8046875 + ], + [ + 0.6796875, + 0.796875 + ], + [ + 0.671875, + 0.7890625 + ], + [ + 0.6640625, + 0.78125 + ], + [ + 0.65625, + 0.7734375 + ], + [ + 0.6484375, + 0.765625 + ], + [ + 0.640625, + 0.7578125 + ], + [ + 0.6328125, + 0.7578125 + ], + [ + 0.625, + 0.75 + ], + [ + 0.6171875, + 0.7421875 + ], + [ + 0.6171875, + 0.734375 + ], + [ + 0.6171875, + 0.7265625 + ], + [ + 0.625, + 0.71875 + ], + [ + 0.625, + 0.7109375 + ], + [ + 0.6328125, + 0.703125 + ], + [ + 0.6328125, + 0.6953125 + ], + [ + 0.640625, + 0.6875 + ], + [ + 0.640625, + 0.6796875 + ], + [ + 0.6484375, + 0.671875 + ], + [ + 0.65625, + 0.671875 + ], + [ + 0.6640625, + 0.671875 + ], + [ + 0.671875, + 0.671875 + ], + [ + 0.6796875, + 0.671875 + ], + [ + 0.6875, + 0.671875 + ], + [ + 0.6953125, + 0.671875 + ], + [ + 0.703125, + 0.6640625 + ], + [ + 0.7109375, + 0.6640625 + ], + [ + 0.71875, + 0.6640625 + ], + [ + 0.7265625, + 0.6640625 + ], + [ + 0.734375, + 0.6640625 + ], + [ + 0.7421875, + 0.6640625 + ], + [ + 0.75, + 0.6640625 + ], + [ + 0.7578125, + 0.65625 + ], + [ + 0.765625, + 0.65625 + ], + [ + 0.7734375, + 0.65625 + ], + [ + 0.78125, + 0.65625 + ], + [ + 0.7890625, + 0.65625 + ], + [ + 0.796875, + 0.65625 + ], + [ + 0.8046875, + 0.6484375 + ], + [ + 0.8125, + 0.6484375 + ], + [ + 0.8203125, + 0.6484375 + ], + [ + 0.828125, + 0.6484375 + ], + [ + 0.8359375, + 0.6484375 + ], + [ + 0.84375, + 0.6484375 + ], + [ + 0.8515625, + 0.6484375 + ], + [ + 0.859375, + 0.640625 + ], + [ + 0.8671875, + 0.640625 + ], + [ + 0.875, + 0.640625 + ], + [ + 0.8828125, + 0.640625 + ], + [ + 0.890625, + 0.640625 + ], + [ + 0.8984375, + 0.640625 + ], + [ + 0.90625, + 0.640625 + ], + [ + 0.9140625, + 0.6328125 + ], + [ + 0.921875, + 0.6328125 + ], + [ + 0.9296875, + 0.6328125 + ], + [ + 0.9375, + 0.6328125 + ], + [ + 0.9453125, + 0.6328125 + ], + [ + 0.953125, + 0.6328125 + ], + [ + 0.9453125, + 0.625 + ], + [ + 0.9375, + 0.6171875 + ], + [ + 0.9296875, + 0.609375 + ], + [ + 0.921875, + 0.6015625 + ], + [ + 0.9140625, + 0.59375 + ], + [ + 0.90625, + 0.5859375 + ], + [ + 0.8984375, + 0.578125 + ], + [ + 0.890625, + 0.5703125 + ], + [ + 0.8828125, + 0.5625 + ], + [ + 0.875, + 0.5546875 + ], + [ + 0.8671875, + 0.546875 + ], + [ + 0.859375, + 0.5390625 + ], + [ + 0.8515625, + 0.53125 + ], + [ + 0.84375, + 0.5234375 + ], + [ + 0.8359375, + 0.515625 + ], + [ + 0.828125, + 0.5078125 + ], + [ + 0.8203125, + 0.5 + ], + [ + 0.8125, + 0.4921875 + ], + [ + 0.8046875, + 0.484375 + ], + [ + 0.796875, + 0.4765625 + ], + [ + 0.7890625, + 0.46875 + ], + [ + 0.78125, + 0.4609375 + ], + [ + 0.7734375, + 0.453125 + ], + [ + 0.765625, + 0.4453125 + ], + [ + 0.7578125, + 0.4375 + ], + [ + 0.75, + 0.4296875 + ], + [ + 0.7421875, + 0.421875 + ], + [ + 0.734375, + 0.4140625 + ], + [ + 0.734375, + 0.40625 + ], + [ + 0.734375, + 0.3984375 + ], + [ + 0.734375, + 0.390625 + ], + [ + 0.734375, + 0.3828125 + ], + [ + 0.734375, + 0.375 + ], + [ + 0.7421875, + 0.3671875 + ], + [ + 0.7421875, + 0.359375 + ], + [ + 0.7421875, + 0.3515625 + ], + [ + 0.7421875, + 0.34375 + ], + [ + 0.7421875, + 0.3359375 + ], + [ + 0.7421875, + 0.328125 + ], + [ + 0.75, + 0.3203125 + ], + [ + 0.75, + 0.3125 + ], + [ + 0.75, + 0.3046875 + ], + [ + 0.75, + 0.296875 + ], + [ + 0.75, + 0.2890625 + ], + [ + 0.75, + 0.28125 + ], + [ + 0.7578125, + 0.2734375 + ], + [ + 0.7578125, + 0.265625 + ], + [ + 0.7578125, + 0.2578125 + ], + [ + 0.7578125, + 0.25 + ], + [ + 0.7578125, + 0.2421875 + ], + [ + 0.7578125, + 0.234375 + ], + [ + 0.765625, + 0.2265625 + ], + [ + 0.765625, + 0.21875 + ], + [ + 0.765625, + 0.2109375 + ], + [ + 0.765625, + 0.203125 + ], + [ + 0.765625, + 0.1953125 + ], + [ + 0.765625, + 0.1875 + ], + [ + 0.7734375, + 0.1796875 + ], + [ + 0.7734375, + 0.171875 + ], + [ + 0.7734375, + 0.1640625 + ], + [ + 0.7734375, + 0.15625 + ], + [ + 0.7734375, + 0.1484375 + ], + [ + 0.7734375, + 0.140625 + ], + [ + 0.78125, + 0.1328125 + ], + [ + 0.78125, + 0.125 + ], + [ + 0.78125, + 0.1171875 + ], + [ + 0.78125, + 0.109375 + ], + [ + 0.78125, + 0.1015625 + ], + [ + 0.7734375, + 0.109375 + ], + [ + 0.765625, + 0.109375 + ], + [ + 0.7578125, + 0.1171875 + ], + [ + 0.75, + 0.1171875 + ], + [ + 0.7421875, + 0.125 + ], + [ + 0.734375, + 0.125 + ], + [ + 0.7265625, + 0.1328125 + ], + [ + 0.71875, + 0.1328125 + ], + [ + 0.7109375, + 0.140625 + ], + [ + 0.703125, + 0.140625 + ], + [ + 0.6953125, + 0.1484375 + ], + [ + 0.6875, + 0.1484375 + ], + [ + 0.6796875, + 0.15625 + ], + [ + 0.671875, + 0.15625 + ], + [ + 0.6640625, + 0.1640625 + ], + [ + 0.65625, + 0.1640625 + ], + [ + 0.6484375, + 0.171875 + ], + [ + 0.640625, + 0.1796875 + ], + [ + 0.6328125, + 0.1796875 + ], + [ + 0.625, + 0.1875 + ], + [ + 0.6171875, + 0.1875 + ], + [ + 0.609375, + 0.1953125 + ], + [ + 0.6015625, + 0.1953125 + ], + [ + 0.59375, + 0.203125 + ], + [ + 0.5859375, + 0.1953125 + ], + [ + 0.5859375, + 0.1875 + ], + [ + 0.5859375, + 0.1796875 + ], + [ + 0.5859375, + 0.171875 + ], + [ + 0.59375, + 0.1640625 + ], + [ + 0.59375, + 0.15625 + ], + [ + 0.59375, + 0.1484375 + ], + [ + 0.59375, + 0.140625 + ], + [ + 0.59375, + 0.1328125 + ], + [ + 0.6015625, + 0.125 + ], + [ + 0.6015625, + 0.1171875 + ], + [ + 0.6015625, + 0.109375 + ], + [ + 0.6015625, + 0.1015625 + ], + [ + 0.6015625, + 0.09375 + ], + [ + 0.609375, + 0.0859375 + ], + [ + 0.609375, + 0.078125 + ], + [ + 0.609375, + 0.0703125 + ], + [ + 0.609375, + 0.0625 + ], + [ + 0.609375, + 0.0546875 + ], + [ + 0.6015625, + 0.0625 + ], + [ + 0.59375, + 0.0625 + ], + [ + 0.5859375, + 0.0703125 + ], + [ + 0.578125, + 0.0703125 + ], + [ + 0.5703125, + 0.078125 + ], + [ + 0.5625, + 0.078125 + ], + [ + 0.5546875, + 0.0859375 + ], + [ + 0.546875, + 0.0859375 + ], + [ + 0.5390625, + 0.09375 + ], + [ + 0.53125, + 0.1015625 + ], + [ + 0.5234375, + 0.1015625 + ], + [ + 0.515625, + 0.109375 + ], + [ + 0.5078125, + 0.109375 + ], + [ + 0.5, + 0.1171875 + ], + [ + 0.4921875, + 0.1171875 + ], + [ + 0.484375, + 0.125 + ], + [ + 0.4765625, + 0.125 + ], + [ + 0.46875, + 0.125 + ], + [ + 0.4609375, + 0.1171875 + ], + [ + 0.453125, + 0.1171875 + ], + [ + 0.4453125, + 0.109375 + ], + [ + 0.4375, + 0.109375 + ], + [ + 0.4296875, + 0.1015625 + ], + [ + 0.421875, + 0.1015625 + ], + [ + 0.4140625, + 0.09375 + ], + [ + 0.40625, + 0.0859375 + ], + [ + 0.3984375, + 0.0859375 + ], + [ + 0.390625, + 0.078125 + ], + [ + 0.3828125, + 0.078125 + ], + [ + 0.375, + 0.0703125 + ], + [ + 0.3671875, + 0.0703125 + ], + [ + 0.359375, + 0.0625 + ], + [ + 0.3515625, + 0.0625 + ] + ] + ], + "12": [ + [ + [ + 0.7578125, + 0.71875 + ], + [ + 0.7578125, + 0.7265625 + ], + [ + 0.7578125, + 0.734375 + ], + [ + 0.7578125, + 0.7421875 + ], + [ + 0.7578125, + 0.75 + ], + [ + 0.7578125, + 0.7578125 + ], + [ + 0.765625, + 0.765625 + ], + [ + 0.765625, + 0.7734375 + ], + [ + 0.765625, + 0.78125 + ], + [ + 0.765625, + 0.7890625 + ], + [ + 0.765625, + 0.796875 + ], + [ + 0.765625, + 0.8046875 + ], + [ + 0.765625, + 0.8125 + ], + [ + 0.7578125, + 0.8203125 + ], + [ + 0.75, + 0.828125 + ], + [ + 0.7421875, + 0.8359375 + ], + [ + 0.734375, + 0.84375 + ], + [ + 0.7265625, + 0.8515625 + ], + [ + 0.71875, + 0.859375 + ], + [ + 0.7109375, + 0.8671875 + ], + [ + 0.703125, + 0.875 + ], + [ + 0.6953125, + 0.8828125 + ], + [ + 0.703125, + 0.8828125 + ], + [ + 0.7109375, + 0.8828125 + ], + [ + 0.71875, + 0.8828125 + ], + [ + 0.7265625, + 0.8828125 + ], + [ + 0.734375, + 0.8828125 + ], + [ + 0.7421875, + 0.8828125 + ], + [ + 0.75, + 0.890625 + ], + [ + 0.7578125, + 0.890625 + ], + [ + 0.765625, + 0.890625 + ], + [ + 0.7734375, + 0.890625 + ], + [ + 0.78125, + 0.890625 + ], + [ + 0.7890625, + 0.890625 + ], + [ + 0.796875, + 0.890625 + ], + [ + 0.8046875, + 0.8984375 + ], + [ + 0.8046875, + 0.90625 + ], + [ + 0.8046875, + 0.9140625 + ], + [ + 0.8125, + 0.921875 + ], + [ + 0.8125, + 0.9296875 + ], + [ + 0.8203125, + 0.9375 + ], + [ + 0.8203125, + 0.9453125 + ], + [ + 0.828125, + 0.953125 + ], + [ + 0.828125, + 0.9609375 + ], + [ + 0.8359375, + 0.96875 + ], + [ + 0.8359375, + 0.9765625 + ], + [ + 0.8359375, + 0.96875 + ], + [ + 0.84375, + 0.9609375 + ], + [ + 0.84375, + 0.953125 + ], + [ + 0.8515625, + 0.9453125 + ], + [ + 0.8515625, + 0.9375 + ], + [ + 0.859375, + 0.9296875 + ], + [ + 0.859375, + 0.921875 + ], + [ + 0.8671875, + 0.9140625 + ], + [ + 0.8671875, + 0.90625 + ], + [ + 0.8671875, + 0.8984375 + ], + [ + 0.875, + 0.890625 + ], + [ + 0.8828125, + 0.890625 + ], + [ + 0.890625, + 0.890625 + ], + [ + 0.8984375, + 0.890625 + ], + [ + 0.90625, + 0.890625 + ], + [ + 0.9140625, + 0.890625 + ], + [ + 0.921875, + 0.890625 + ], + [ + 0.9296875, + 0.8828125 + ], + [ + 0.9375, + 0.8828125 + ], + [ + 0.9453125, + 0.8828125 + ], + [ + 0.953125, + 0.8828125 + ], + [ + 0.9609375, + 0.8828125 + ], + [ + 0.96875, + 0.8828125 + ], + [ + 0.9765625, + 0.8828125 + ], + [ + 0.96875, + 0.875 + ], + [ + 0.9609375, + 0.8671875 + ], + [ + 0.953125, + 0.859375 + ], + [ + 0.9453125, + 0.8515625 + ], + [ + 0.9375, + 0.84375 + ], + [ + 0.9296875, + 0.8359375 + ], + [ + 0.921875, + 0.828125 + ], + [ + 0.9140625, + 0.8203125 + ], + [ + 0.90625, + 0.8125 + ], + [ + 0.90625, + 0.8046875 + ], + [ + 0.90625, + 0.796875 + ], + [ + 0.90625, + 0.7890625 + ], + [ + 0.90625, + 0.78125 + ], + [ + 0.90625, + 0.7734375 + ], + [ + 0.90625, + 0.765625 + ], + [ + 0.9140625, + 0.7578125 + ], + [ + 0.9140625, + 0.75 + ], + [ + 0.9140625, + 0.7421875 + ], + [ + 0.9140625, + 0.734375 + ], + [ + 0.9140625, + 0.7265625 + ], + [ + 0.9140625, + 0.71875 + ], + [ + 0.90625, + 0.7265625 + ], + [ + 0.8984375, + 0.7265625 + ], + [ + 0.890625, + 0.734375 + ], + [ + 0.8828125, + 0.734375 + ], + [ + 0.875, + 0.7421875 + ], + [ + 0.8671875, + 0.7421875 + ], + [ + 0.859375, + 0.75 + ], + [ + 0.8515625, + 0.75 + ], + [ + 0.84375, + 0.7578125 + ], + [ + 0.8359375, + 0.7578125 + ], + [ + 0.828125, + 0.7578125 + ], + [ + 0.8203125, + 0.75 + ], + [ + 0.8125, + 0.75 + ], + [ + 0.8046875, + 0.7421875 + ], + [ + 0.796875, + 0.7421875 + ], + [ + 0.7890625, + 0.734375 + ], + [ + 0.78125, + 0.734375 + ], + [ + 0.7734375, + 0.7265625 + ], + [ + 0.765625, + 0.7265625 + ] + ], + [ + [ + 0.25, + 0.4375 + ], + [ + 0.25, + 0.4453125 + ], + [ + 0.25, + 0.453125 + ], + [ + 0.25, + 0.4609375 + ], + [ + 0.2578125, + 0.46875 + ], + [ + 0.2578125, + 0.4765625 + ], + [ + 0.2578125, + 0.484375 + ], + [ + 0.2578125, + 0.4921875 + ], + [ + 0.2578125, + 0.5 + ], + [ + 0.2578125, + 0.5078125 + ], + [ + 0.25, + 0.515625 + ], + [ + 0.2421875, + 0.5234375 + ], + [ + 0.234375, + 0.53125 + ], + [ + 0.2265625, + 0.53125 + ], + [ + 0.21875, + 0.5390625 + ], + [ + 0.2109375, + 0.546875 + ], + [ + 0.203125, + 0.5546875 + ], + [ + 0.2109375, + 0.5546875 + ], + [ + 0.21875, + 0.5546875 + ], + [ + 0.2265625, + 0.5546875 + ], + [ + 0.234375, + 0.5546875 + ], + [ + 0.2421875, + 0.5625 + ], + [ + 0.25, + 0.5625 + ], + [ + 0.2578125, + 0.5625 + ], + [ + 0.265625, + 0.5625 + ], + [ + 0.2734375, + 0.5625 + ], + [ + 0.28125, + 0.5625 + ], + [ + 0.2890625, + 0.5703125 + ], + [ + 0.2890625, + 0.578125 + ], + [ + 0.2890625, + 0.5859375 + ], + [ + 0.296875, + 0.59375 + ], + [ + 0.296875, + 0.6015625 + ], + [ + 0.3046875, + 0.609375 + ], + [ + 0.3046875, + 0.6171875 + ], + [ + 0.3125, + 0.625 + ], + [ + 0.3125, + 0.6328125 + ], + [ + 0.3125, + 0.625 + ], + [ + 0.3203125, + 0.6171875 + ], + [ + 0.3203125, + 0.609375 + ], + [ + 0.328125, + 0.6015625 + ], + [ + 0.328125, + 0.59375 + ], + [ + 0.3359375, + 0.5859375 + ], + [ + 0.3359375, + 0.578125 + ], + [ + 0.3359375, + 0.5703125 + ], + [ + 0.34375, + 0.5625 + ], + [ + 0.3515625, + 0.5625 + ], + [ + 0.359375, + 0.5625 + ], + [ + 0.3671875, + 0.5625 + ], + [ + 0.375, + 0.5625 + ], + [ + 0.3828125, + 0.5625 + ], + [ + 0.390625, + 0.5546875 + ], + [ + 0.3984375, + 0.5546875 + ], + [ + 0.40625, + 0.5546875 + ], + [ + 0.4140625, + 0.5546875 + ], + [ + 0.421875, + 0.5546875 + ], + [ + 0.4140625, + 0.546875 + ], + [ + 0.40625, + 0.5390625 + ], + [ + 0.3984375, + 0.53125 + ], + [ + 0.390625, + 0.53125 + ], + [ + 0.3828125, + 0.5234375 + ], + [ + 0.375, + 0.515625 + ], + [ + 0.3671875, + 0.5078125 + ], + [ + 0.3671875, + 0.5 + ], + [ + 0.3671875, + 0.4921875 + ], + [ + 0.3671875, + 0.484375 + ], + [ + 0.3671875, + 0.4765625 + ], + [ + 0.3671875, + 0.46875 + ], + [ + 0.375, + 0.4609375 + ], + [ + 0.375, + 0.453125 + ], + [ + 0.375, + 0.4453125 + ], + [ + 0.375, + 0.4375 + ], + [ + 0.3671875, + 0.4375 + ], + [ + 0.359375, + 0.4453125 + ], + [ + 0.3515625, + 0.4453125 + ], + [ + 0.34375, + 0.453125 + ], + [ + 0.3359375, + 0.453125 + ], + [ + 0.328125, + 0.4609375 + ], + [ + 0.3203125, + 0.4609375 + ], + [ + 0.3125, + 0.4609375 + ], + [ + 0.3046875, + 0.4609375 + ], + [ + 0.296875, + 0.4609375 + ], + [ + 0.2890625, + 0.453125 + ], + [ + 0.28125, + 0.453125 + ], + [ + 0.2734375, + 0.4453125 + ], + [ + 0.265625, + 0.4453125 + ], + [ + 0.2578125, + 0.4375 + ] + ], + [ + [ + 0.171875, + 0.09375 + ], + [ + 0.171875, + 0.1015625 + ], + [ + 0.171875, + 0.109375 + ], + [ + 0.171875, + 0.1171875 + ], + [ + 0.171875, + 0.125 + ], + [ + 0.171875, + 0.1328125 + ], + [ + 0.1796875, + 0.140625 + ], + [ + 0.1796875, + 0.1484375 + ], + [ + 0.1796875, + 0.15625 + ], + [ + 0.1796875, + 0.1640625 + ], + [ + 0.1796875, + 0.171875 + ], + [ + 0.1796875, + 0.1796875 + ], + [ + 0.1796875, + 0.1875 + ], + [ + 0.1796875, + 0.1953125 + ], + [ + 0.171875, + 0.203125 + ], + [ + 0.1640625, + 0.2109375 + ], + [ + 0.15625, + 0.21875 + ], + [ + 0.1484375, + 0.2265625 + ], + [ + 0.140625, + 0.234375 + ], + [ + 0.1328125, + 0.2421875 + ], + [ + 0.125, + 0.25 + ], + [ + 0.1171875, + 0.2578125 + ], + [ + 0.109375, + 0.265625 + ], + [ + 0.1171875, + 0.265625 + ], + [ + 0.125, + 0.265625 + ], + [ + 0.1328125, + 0.265625 + ], + [ + 0.140625, + 0.265625 + ], + [ + 0.1484375, + 0.265625 + ], + [ + 0.15625, + 0.265625 + ], + [ + 0.1640625, + 0.2734375 + ], + [ + 0.171875, + 0.2734375 + ], + [ + 0.1796875, + 0.2734375 + ], + [ + 0.1875, + 0.2734375 + ], + [ + 0.1953125, + 0.2734375 + ], + [ + 0.203125, + 0.2734375 + ], + [ + 0.2109375, + 0.2734375 + ], + [ + 0.21875, + 0.28125 + ], + [ + 0.21875, + 0.2890625 + ], + [ + 0.21875, + 0.296875 + ], + [ + 0.2265625, + 0.3046875 + ], + [ + 0.2265625, + 0.3125 + ], + [ + 0.234375, + 0.3203125 + ], + [ + 0.234375, + 0.328125 + ], + [ + 0.2421875, + 0.3359375 + ], + [ + 0.2421875, + 0.34375 + ], + [ + 0.25, + 0.3515625 + ], + [ + 0.25, + 0.359375 + ], + [ + 0.2578125, + 0.3671875 + ], + [ + 0.2578125, + 0.375 + ], + [ + 0.2578125, + 0.3671875 + ], + [ + 0.265625, + 0.359375 + ], + [ + 0.265625, + 0.3515625 + ], + [ + 0.2734375, + 0.34375 + ], + [ + 0.2734375, + 0.3359375 + ], + [ + 0.28125, + 0.328125 + ], + [ + 0.28125, + 0.3203125 + ], + [ + 0.2890625, + 0.3125 + ], + [ + 0.2890625, + 0.3046875 + ], + [ + 0.296875, + 0.296875 + ], + [ + 0.296875, + 0.2890625 + ], + [ + 0.296875, + 0.28125 + ], + [ + 0.3046875, + 0.2734375 + ], + [ + 0.3125, + 0.2734375 + ], + [ + 0.3203125, + 0.2734375 + ], + [ + 0.328125, + 0.2734375 + ], + [ + 0.3359375, + 0.2734375 + ], + [ + 0.34375, + 0.2734375 + ], + [ + 0.3515625, + 0.2734375 + ], + [ + 0.359375, + 0.265625 + ], + [ + 0.3671875, + 0.265625 + ], + [ + 0.375, + 0.265625 + ], + [ + 0.3828125, + 0.265625 + ], + [ + 0.390625, + 0.265625 + ], + [ + 0.3984375, + 0.265625 + ], + [ + 0.40625, + 0.265625 + ], + [ + 0.3984375, + 0.2578125 + ], + [ + 0.390625, + 0.25 + ], + [ + 0.3828125, + 0.2421875 + ], + [ + 0.375, + 0.234375 + ], + [ + 0.3671875, + 0.2265625 + ], + [ + 0.359375, + 0.21875 + ], + [ + 0.3515625, + 0.2109375 + ], + [ + 0.34375, + 0.203125 + ], + [ + 0.3359375, + 0.1953125 + ], + [ + 0.3359375, + 0.1875 + ], + [ + 0.3359375, + 0.1796875 + ], + [ + 0.3359375, + 0.171875 + ], + [ + 0.3359375, + 0.1640625 + ], + [ + 0.3359375, + 0.15625 + ], + [ + 0.3359375, + 0.1484375 + ], + [ + 0.3359375, + 0.140625 + ], + [ + 0.34375, + 0.1328125 + ], + [ + 0.34375, + 0.125 + ], + [ + 0.34375, + 0.1171875 + ], + [ + 0.34375, + 0.109375 + ], + [ + 0.34375, + 0.1015625 + ], + [ + 0.34375, + 0.09375 + ], + [ + 0.3359375, + 0.09375 + ], + [ + 0.328125, + 0.1015625 + ], + [ + 0.3203125, + 0.1015625 + ], + [ + 0.3125, + 0.109375 + ], + [ + 0.3046875, + 0.109375 + ], + [ + 0.296875, + 0.1171875 + ], + [ + 0.2890625, + 0.1171875 + ], + [ + 0.28125, + 0.125 + ], + [ + 0.2734375, + 0.125 + ], + [ + 0.265625, + 0.1328125 + ], + [ + 0.2578125, + 0.1328125 + ], + [ + 0.25, + 0.1328125 + ], + [ + 0.2421875, + 0.125 + ], + [ + 0.234375, + 0.125 + ], + [ + 0.2265625, + 0.1171875 + ], + [ + 0.21875, + 0.1171875 + ], + [ + 0.2109375, + 0.109375 + ], + [ + 0.203125, + 0.109375 + ], + [ + 0.1953125, + 0.1015625 + ], + [ + 0.1875, + 0.1015625 + ], + [ + 0.1796875, + 0.09375 + ] + ] + ], + "13": [ + [ + [ + 0.359375, + 0.6640625 + ], + [ + 0.359375, + 0.671875 + ], + [ + 0.3515625, + 0.6796875 + ], + [ + 0.3515625, + 0.6875 + ], + [ + 0.34375, + 0.6953125 + ], + [ + 0.34375, + 0.703125 + ], + [ + 0.3359375, + 0.7109375 + ], + [ + 0.328125, + 0.71875 + ], + [ + 0.328125, + 0.7265625 + ], + [ + 0.3203125, + 0.734375 + ], + [ + 0.3203125, + 0.7421875 + ], + [ + 0.3125, + 0.75 + ], + [ + 0.3046875, + 0.7578125 + ], + [ + 0.3046875, + 0.765625 + ], + [ + 0.296875, + 0.7734375 + ], + [ + 0.296875, + 0.78125 + ], + [ + 0.2890625, + 0.7890625 + ], + [ + 0.2890625, + 0.796875 + ], + [ + 0.2890625, + 0.8046875 + ], + [ + 0.296875, + 0.8125 + ], + [ + 0.296875, + 0.8203125 + ], + [ + 0.3046875, + 0.828125 + ], + [ + 0.3046875, + 0.8359375 + ], + [ + 0.3125, + 0.84375 + ], + [ + 0.3203125, + 0.8515625 + ], + [ + 0.3203125, + 0.859375 + ], + [ + 0.328125, + 0.8671875 + ], + [ + 0.328125, + 0.875 + ], + [ + 0.3359375, + 0.8828125 + ], + [ + 0.34375, + 0.890625 + ], + [ + 0.34375, + 0.8984375 + ], + [ + 0.3515625, + 0.90625 + ], + [ + 0.3515625, + 0.9140625 + ], + [ + 0.359375, + 0.921875 + ], + [ + 0.3671875, + 0.921875 + ], + [ + 0.375, + 0.921875 + ], + [ + 0.3828125, + 0.921875 + ], + [ + 0.390625, + 0.921875 + ], + [ + 0.3984375, + 0.921875 + ], + [ + 0.40625, + 0.921875 + ], + [ + 0.4140625, + 0.921875 + ], + [ + 0.421875, + 0.921875 + ], + [ + 0.4296875, + 0.921875 + ], + [ + 0.4375, + 0.921875 + ], + [ + 0.4453125, + 0.921875 + ], + [ + 0.453125, + 0.921875 + ], + [ + 0.4609375, + 0.921875 + ], + [ + 0.46875, + 0.921875 + ], + [ + 0.4765625, + 0.921875 + ], + [ + 0.484375, + 0.921875 + ], + [ + 0.4921875, + 0.921875 + ], + [ + 0.5, + 0.921875 + ], + [ + 0.5078125, + 0.921875 + ], + [ + 0.515625, + 0.921875 + ], + [ + 0.5234375, + 0.921875 + ], + [ + 0.53125, + 0.9140625 + ], + [ + 0.53125, + 0.90625 + ], + [ + 0.5390625, + 0.8984375 + ], + [ + 0.546875, + 0.890625 + ], + [ + 0.546875, + 0.8828125 + ], + [ + 0.5546875, + 0.875 + ], + [ + 0.5625, + 0.8671875 + ], + [ + 0.5625, + 0.859375 + ], + [ + 0.5703125, + 0.8515625 + ], + [ + 0.578125, + 0.84375 + ], + [ + 0.578125, + 0.8359375 + ], + [ + 0.5859375, + 0.828125 + ], + [ + 0.59375, + 0.8203125 + ], + [ + 0.59375, + 0.8125 + ], + [ + 0.6015625, + 0.8046875 + ], + [ + 0.6015625, + 0.796875 + ], + [ + 0.6015625, + 0.7890625 + ], + [ + 0.59375, + 0.78125 + ], + [ + 0.59375, + 0.7734375 + ], + [ + 0.5859375, + 0.765625 + ], + [ + 0.578125, + 0.7578125 + ], + [ + 0.578125, + 0.75 + ], + [ + 0.5703125, + 0.7421875 + ], + [ + 0.5625, + 0.734375 + ], + [ + 0.5625, + 0.7265625 + ], + [ + 0.5546875, + 0.71875 + ], + [ + 0.546875, + 0.7109375 + ], + [ + 0.546875, + 0.703125 + ], + [ + 0.5390625, + 0.6953125 + ], + [ + 0.53125, + 0.6875 + ], + [ + 0.53125, + 0.6796875 + ], + [ + 0.5234375, + 0.671875 + ], + [ + 0.5234375, + 0.6640625 + ], + [ + 0.515625, + 0.6640625 + ], + [ + 0.5078125, + 0.6640625 + ], + [ + 0.5, + 0.6640625 + ], + [ + 0.4921875, + 0.6640625 + ], + [ + 0.484375, + 0.6640625 + ], + [ + 0.4765625, + 0.6640625 + ], + [ + 0.46875, + 0.6640625 + ], + [ + 0.4609375, + 0.6640625 + ], + [ + 0.453125, + 0.6640625 + ], + [ + 0.4453125, + 0.6640625 + ], + [ + 0.4375, + 0.6640625 + ], + [ + 0.4296875, + 0.6640625 + ], + [ + 0.421875, + 0.6640625 + ], + [ + 0.4140625, + 0.6640625 + ], + [ + 0.40625, + 0.6640625 + ], + [ + 0.3984375, + 0.6640625 + ], + [ + 0.390625, + 0.6640625 + ], + [ + 0.3828125, + 0.6640625 + ], + [ + 0.375, + 0.6640625 + ], + [ + 0.3671875, + 0.6640625 + ] + ], + [ + [ + 0.03125, + 0.15625 + ], + [ + 0.03125, + 0.1640625 + ], + [ + 0.0234375, + 0.171875 + ], + [ + 0.015625, + 0.1796875 + ], + [ + 0.015625, + 0.1875 + ], + [ + 0.0078125, + 0.1953125 + ], + [ + 0.0078125, + 0.203125 + ], + [ + 0.0078125, + 0.2109375 + ], + [ + 0.015625, + 0.21875 + ], + [ + 0.015625, + 0.2265625 + ], + [ + 0.0234375, + 0.234375 + ], + [ + 0.0234375, + 0.2421875 + ], + [ + 0.03125, + 0.25 + ], + [ + 0.0390625, + 0.25 + ], + [ + 0.046875, + 0.25 + ], + [ + 0.0546875, + 0.25 + ], + [ + 0.0625, + 0.25 + ], + [ + 0.0703125, + 0.25 + ], + [ + 0.078125, + 0.25 + ], + [ + 0.0859375, + 0.25 + ], + [ + 0.09375, + 0.25 + ], + [ + 0.1015625, + 0.2421875 + ], + [ + 0.1015625, + 0.234375 + ], + [ + 0.109375, + 0.2265625 + ], + [ + 0.109375, + 0.21875 + ], + [ + 0.1171875, + 0.2109375 + ], + [ + 0.1171875, + 0.203125 + ], + [ + 0.1171875, + 0.1953125 + ], + [ + 0.109375, + 0.1875 + ], + [ + 0.109375, + 0.1796875 + ], + [ + 0.1015625, + 0.171875 + ], + [ + 0.09375, + 0.1640625 + ], + [ + 0.09375, + 0.15625 + ], + [ + 0.0859375, + 0.15625 + ], + [ + 0.078125, + 0.15625 + ], + [ + 0.0703125, + 0.15625 + ], + [ + 0.0625, + 0.15625 + ], + [ + 0.0546875, + 0.15625 + ], + [ + 0.046875, + 0.15625 + ], + [ + 0.0390625, + 0.15625 + ] + ], + [ + [ + 0.609375, + 0.046875 + ], + [ + 0.609375, + 0.0546875 + ], + [ + 0.6015625, + 0.0625 + ], + [ + 0.6015625, + 0.0703125 + ], + [ + 0.59375, + 0.078125 + ], + [ + 0.59375, + 0.0859375 + ], + [ + 0.59375, + 0.09375 + ], + [ + 0.6015625, + 0.1015625 + ], + [ + 0.6015625, + 0.109375 + ], + [ + 0.609375, + 0.1171875 + ], + [ + 0.6171875, + 0.1171875 + ], + [ + 0.625, + 0.1171875 + ], + [ + 0.6328125, + 0.1171875 + ], + [ + 0.640625, + 0.1171875 + ], + [ + 0.6484375, + 0.1171875 + ], + [ + 0.65625, + 0.1171875 + ], + [ + 0.6640625, + 0.1171875 + ], + [ + 0.671875, + 0.109375 + ], + [ + 0.6796875, + 0.1015625 + ], + [ + 0.6875, + 0.09375 + ], + [ + 0.6875, + 0.0859375 + ], + [ + 0.6875, + 0.078125 + ], + [ + 0.6796875, + 0.0703125 + ], + [ + 0.671875, + 0.0625 + ], + [ + 0.6640625, + 0.0546875 + ], + [ + 0.6640625, + 0.046875 + ], + [ + 0.65625, + 0.046875 + ], + [ + 0.6484375, + 0.046875 + ], + [ + 0.640625, + 0.046875 + ], + [ + 0.6328125, + 0.046875 + ], + [ + 0.625, + 0.046875 + ], + [ + 0.6171875, + 0.046875 + ] + ] + ], + "14": [ + [ + [ + 0.234375, + 0.0 + ], + [ + 0.234375, + 0.0078125 + ], + [ + 0.2265625, + 0.015625 + ], + [ + 0.2265625, + 0.0234375 + ], + [ + 0.21875, + 0.03125 + ], + [ + 0.21875, + 0.0390625 + ], + [ + 0.2109375, + 0.046875 + ], + [ + 0.203125, + 0.0546875 + ], + [ + 0.203125, + 0.0625 + ], + [ + 0.1953125, + 0.0703125 + ], + [ + 0.1953125, + 0.078125 + ], + [ + 0.1875, + 0.0859375 + ], + [ + 0.1796875, + 0.09375 + ], + [ + 0.1796875, + 0.1015625 + ], + [ + 0.171875, + 0.109375 + ], + [ + 0.171875, + 0.1171875 + ], + [ + 0.1640625, + 0.125 + ], + [ + 0.15625, + 0.1328125 + ], + [ + 0.15625, + 0.140625 + ], + [ + 0.1484375, + 0.1484375 + ], + [ + 0.1484375, + 0.15625 + ], + [ + 0.140625, + 0.1640625 + ], + [ + 0.140625, + 0.171875 + ], + [ + 0.1328125, + 0.1796875 + ], + [ + 0.125, + 0.1875 + ], + [ + 0.125, + 0.1953125 + ], + [ + 0.1171875, + 0.203125 + ], + [ + 0.1171875, + 0.2109375 + ], + [ + 0.109375, + 0.21875 + ], + [ + 0.1015625, + 0.2265625 + ], + [ + 0.1015625, + 0.234375 + ], + [ + 0.09375, + 0.2421875 + ], + [ + 0.09375, + 0.25 + ], + [ + 0.0859375, + 0.2578125 + ], + [ + 0.078125, + 0.265625 + ], + [ + 0.078125, + 0.2734375 + ], + [ + 0.0703125, + 0.28125 + ], + [ + 0.0703125, + 0.2890625 + ], + [ + 0.0625, + 0.296875 + ], + [ + 0.0625, + 0.3046875 + ], + [ + 0.0546875, + 0.3125 + ], + [ + 0.046875, + 0.3203125 + ], + [ + 0.046875, + 0.328125 + ], + [ + 0.0390625, + 0.3359375 + ], + [ + 0.0390625, + 0.34375 + ], + [ + 0.03125, + 0.3515625 + ], + [ + 0.0234375, + 0.359375 + ], + [ + 0.0234375, + 0.3671875 + ], + [ + 0.015625, + 0.375 + ], + [ + 0.015625, + 0.3828125 + ], + [ + 0.0078125, + 0.390625 + ], + [ + 0.0078125, + 0.3984375 + ], + [ + 0.0078125, + 0.40625 + ], + [ + 0.015625, + 0.4140625 + ], + [ + 0.015625, + 0.421875 + ], + [ + 0.0234375, + 0.4296875 + ], + [ + 0.0234375, + 0.4375 + ], + [ + 0.03125, + 0.4453125 + ], + [ + 0.0390625, + 0.453125 + ], + [ + 0.0390625, + 0.4609375 + ], + [ + 0.046875, + 0.46875 + ], + [ + 0.046875, + 0.4765625 + ], + [ + 0.0546875, + 0.484375 + ], + [ + 0.0546875, + 0.4921875 + ], + [ + 0.0625, + 0.5 + ], + [ + 0.0703125, + 0.5078125 + ], + [ + 0.0703125, + 0.515625 + ], + [ + 0.078125, + 0.5234375 + ], + [ + 0.078125, + 0.53125 + ], + [ + 0.0859375, + 0.5390625 + ], + [ + 0.0859375, + 0.546875 + ], + [ + 0.09375, + 0.5546875 + ], + [ + 0.1015625, + 0.5625 + ], + [ + 0.1015625, + 0.5703125 + ], + [ + 0.109375, + 0.578125 + ], + [ + 0.109375, + 0.5859375 + ], + [ + 0.1171875, + 0.59375 + ], + [ + 0.125, + 0.6015625 + ], + [ + 0.125, + 0.609375 + ], + [ + 0.1328125, + 0.6171875 + ], + [ + 0.1328125, + 0.625 + ], + [ + 0.140625, + 0.6328125 + ], + [ + 0.140625, + 0.640625 + ], + [ + 0.1484375, + 0.6484375 + ], + [ + 0.15625, + 0.65625 + ], + [ + 0.15625, + 0.6640625 + ], + [ + 0.1640625, + 0.671875 + ], + [ + 0.1640625, + 0.6796875 + ], + [ + 0.171875, + 0.6875 + ], + [ + 0.171875, + 0.6953125 + ], + [ + 0.1796875, + 0.703125 + ], + [ + 0.1875, + 0.7109375 + ], + [ + 0.1875, + 0.71875 + ], + [ + 0.1953125, + 0.7265625 + ], + [ + 0.1953125, + 0.734375 + ], + [ + 0.203125, + 0.7421875 + ], + [ + 0.203125, + 0.75 + ], + [ + 0.2109375, + 0.7578125 + ], + [ + 0.21875, + 0.765625 + ], + [ + 0.21875, + 0.7734375 + ], + [ + 0.2265625, + 0.78125 + ], + [ + 0.2265625, + 0.7890625 + ], + [ + 0.234375, + 0.796875 + ], + [ + 0.2421875, + 0.796875 + ], + [ + 0.25, + 0.796875 + ], + [ + 0.2578125, + 0.796875 + ], + [ + 0.265625, + 0.796875 + ], + [ + 0.2734375, + 0.796875 + ], + [ + 0.28125, + 0.796875 + ], + [ + 0.2890625, + 0.796875 + ], + [ + 0.296875, + 0.796875 + ], + [ + 0.3046875, + 0.796875 + ], + [ + 0.3125, + 0.796875 + ], + [ + 0.3203125, + 0.796875 + ], + [ + 0.328125, + 0.796875 + ], + [ + 0.3359375, + 0.796875 + ], + [ + 0.34375, + 0.796875 + ], + [ + 0.3515625, + 0.796875 + ], + [ + 0.359375, + 0.796875 + ], + [ + 0.3671875, + 0.796875 + ], + [ + 0.375, + 0.796875 + ], + [ + 0.3828125, + 0.796875 + ], + [ + 0.390625, + 0.796875 + ], + [ + 0.3984375, + 0.796875 + ], + [ + 0.40625, + 0.796875 + ], + [ + 0.4140625, + 0.796875 + ], + [ + 0.421875, + 0.796875 + ], + [ + 0.4296875, + 0.796875 + ], + [ + 0.4375, + 0.796875 + ], + [ + 0.4453125, + 0.796875 + ], + [ + 0.453125, + 0.796875 + ], + [ + 0.4609375, + 0.796875 + ], + [ + 0.46875, + 0.796875 + ], + [ + 0.4765625, + 0.796875 + ], + [ + 0.484375, + 0.796875 + ], + [ + 0.4921875, + 0.796875 + ], + [ + 0.5, + 0.796875 + ], + [ + 0.5078125, + 0.796875 + ], + [ + 0.515625, + 0.796875 + ], + [ + 0.5234375, + 0.796875 + ], + [ + 0.53125, + 0.796875 + ], + [ + 0.5390625, + 0.796875 + ], + [ + 0.546875, + 0.796875 + ], + [ + 0.5546875, + 0.796875 + ], + [ + 0.5625, + 0.796875 + ], + [ + 0.5703125, + 0.796875 + ], + [ + 0.578125, + 0.796875 + ], + [ + 0.5859375, + 0.796875 + ], + [ + 0.59375, + 0.796875 + ], + [ + 0.6015625, + 0.796875 + ], + [ + 0.609375, + 0.796875 + ], + [ + 0.6171875, + 0.796875 + ], + [ + 0.625, + 0.796875 + ], + [ + 0.6328125, + 0.796875 + ], + [ + 0.640625, + 0.796875 + ], + [ + 0.6484375, + 0.796875 + ], + [ + 0.65625, + 0.796875 + ], + [ + 0.6640625, + 0.796875 + ], + [ + 0.671875, + 0.796875 + ], + [ + 0.6796875, + 0.796875 + ], + [ + 0.6875, + 0.796875 + ], + [ + 0.6953125, + 0.796875 + ], + [ + 0.703125, + 0.796875 + ], + [ + 0.7109375, + 0.7890625 + ], + [ + 0.7109375, + 0.78125 + ], + [ + 0.71875, + 0.7734375 + ], + [ + 0.71875, + 0.765625 + ], + [ + 0.7265625, + 0.7578125 + ], + [ + 0.734375, + 0.75 + ], + [ + 0.734375, + 0.7421875 + ], + [ + 0.7421875, + 0.734375 + ], + [ + 0.7421875, + 0.7265625 + ], + [ + 0.75, + 0.71875 + ], + [ + 0.75, + 0.7109375 + ], + [ + 0.7578125, + 0.703125 + ], + [ + 0.765625, + 0.6953125 + ], + [ + 0.765625, + 0.6875 + ], + [ + 0.7734375, + 0.6796875 + ], + [ + 0.7734375, + 0.671875 + ], + [ + 0.78125, + 0.6640625 + ], + [ + 0.78125, + 0.65625 + ], + [ + 0.7890625, + 0.6484375 + ], + [ + 0.796875, + 0.640625 + ], + [ + 0.796875, + 0.6328125 + ], + [ + 0.8046875, + 0.625 + ], + [ + 0.8046875, + 0.6171875 + ], + [ + 0.8125, + 0.609375 + ], + [ + 0.8125, + 0.6015625 + ], + [ + 0.8203125, + 0.59375 + ], + [ + 0.828125, + 0.5859375 + ], + [ + 0.828125, + 0.578125 + ], + [ + 0.8359375, + 0.5703125 + ], + [ + 0.8359375, + 0.5625 + ], + [ + 0.84375, + 0.5546875 + ], + [ + 0.8515625, + 0.546875 + ], + [ + 0.8515625, + 0.5390625 + ], + [ + 0.859375, + 0.53125 + ], + [ + 0.859375, + 0.5234375 + ], + [ + 0.8671875, + 0.515625 + ], + [ + 0.8671875, + 0.5078125 + ], + [ + 0.875, + 0.5 + ], + [ + 0.8828125, + 0.4921875 + ], + [ + 0.8828125, + 0.484375 + ], + [ + 0.890625, + 0.4765625 + ], + [ + 0.890625, + 0.46875 + ], + [ + 0.8984375, + 0.4609375 + ], + [ + 0.8984375, + 0.453125 + ], + [ + 0.90625, + 0.4453125 + ], + [ + 0.9140625, + 0.4375 + ], + [ + 0.9140625, + 0.4296875 + ], + [ + 0.921875, + 0.421875 + ], + [ + 0.921875, + 0.4140625 + ], + [ + 0.9296875, + 0.40625 + ], + [ + 0.9296875, + 0.3984375 + ], + [ + 0.9296875, + 0.390625 + ], + [ + 0.921875, + 0.3828125 + ], + [ + 0.921875, + 0.375 + ], + [ + 0.9140625, + 0.3671875 + ], + [ + 0.9140625, + 0.359375 + ], + [ + 0.90625, + 0.3515625 + ], + [ + 0.8984375, + 0.34375 + ], + [ + 0.8984375, + 0.3359375 + ], + [ + 0.890625, + 0.328125 + ], + [ + 0.890625, + 0.3203125 + ], + [ + 0.8828125, + 0.3125 + ], + [ + 0.875, + 0.3046875 + ], + [ + 0.875, + 0.296875 + ], + [ + 0.8671875, + 0.2890625 + ], + [ + 0.8671875, + 0.28125 + ], + [ + 0.859375, + 0.2734375 + ], + [ + 0.859375, + 0.265625 + ], + [ + 0.8515625, + 0.2578125 + ], + [ + 0.84375, + 0.25 + ], + [ + 0.84375, + 0.2421875 + ], + [ + 0.8359375, + 0.234375 + ], + [ + 0.8359375, + 0.2265625 + ], + [ + 0.828125, + 0.21875 + ], + [ + 0.8203125, + 0.2109375 + ], + [ + 0.8203125, + 0.203125 + ], + [ + 0.8125, + 0.1953125 + ], + [ + 0.8125, + 0.1875 + ], + [ + 0.8046875, + 0.1796875 + ], + [ + 0.796875, + 0.171875 + ], + [ + 0.796875, + 0.1640625 + ], + [ + 0.7890625, + 0.15625 + ], + [ + 0.7890625, + 0.1484375 + ], + [ + 0.78125, + 0.140625 + ], + [ + 0.78125, + 0.1328125 + ], + [ + 0.7734375, + 0.125 + ], + [ + 0.765625, + 0.1171875 + ], + [ + 0.765625, + 0.109375 + ], + [ + 0.7578125, + 0.1015625 + ], + [ + 0.7578125, + 0.09375 + ], + [ + 0.75, + 0.0859375 + ], + [ + 0.7421875, + 0.078125 + ], + [ + 0.7421875, + 0.0703125 + ], + [ + 0.734375, + 0.0625 + ], + [ + 0.734375, + 0.0546875 + ], + [ + 0.7265625, + 0.046875 + ], + [ + 0.71875, + 0.0390625 + ], + [ + 0.71875, + 0.03125 + ], + [ + 0.7109375, + 0.0234375 + ], + [ + 0.7109375, + 0.015625 + ], + [ + 0.703125, + 0.0078125 + ], + [ + 0.703125, + 0.0 + ], + [ + 0.6953125, + 0.0 + ], + [ + 0.6875, + 0.0 + ], + [ + 0.6796875, + 0.0 + ], + [ + 0.671875, + 0.0 + ], + [ + 0.6640625, + 0.0 + ], + [ + 0.65625, + 0.0 + ], + [ + 0.6484375, + 0.0 + ], + [ + 0.640625, + 0.0 + ], + [ + 0.6328125, + 0.0 + ], + [ + 0.625, + 0.0 + ], + [ + 0.6171875, + 0.0 + ], + [ + 0.609375, + 0.0 + ], + [ + 0.6015625, + 0.0 + ], + [ + 0.59375, + 0.0 + ], + [ + 0.5859375, + 0.0 + ], + [ + 0.578125, + 0.0 + ], + [ + 0.5703125, + 0.0 + ], + [ + 0.5625, + 0.0 + ], + [ + 0.5546875, + 0.0 + ], + [ + 0.546875, + 0.0 + ], + [ + 0.5390625, + 0.0 + ], + [ + 0.53125, + 0.0 + ], + [ + 0.5234375, + 0.0 + ], + [ + 0.515625, + 0.0 + ], + [ + 0.5078125, + 0.0 + ], + [ + 0.5, + 0.0 + ], + [ + 0.4921875, + 0.0 + ], + [ + 0.484375, + 0.0 + ], + [ + 0.4765625, + 0.0 + ], + [ + 0.46875, + 0.0 + ], + [ + 0.4609375, + 0.0 + ], + [ + 0.453125, + 0.0 + ], + [ + 0.4453125, + 0.0 + ], + [ + 0.4375, + 0.0 + ], + [ + 0.4296875, + 0.0 + ], + [ + 0.421875, + 0.0 + ], + [ + 0.4140625, + 0.0 + ], + [ + 0.40625, + 0.0 + ], + [ + 0.3984375, + 0.0 + ], + [ + 0.390625, + 0.0 + ], + [ + 0.3828125, + 0.0 + ], + [ + 0.375, + 0.0 + ], + [ + 0.3671875, + 0.0 + ], + [ + 0.359375, + 0.0 + ], + [ + 0.3515625, + 0.0 + ], + [ + 0.34375, + 0.0 + ], + [ + 0.3359375, + 0.0 + ], + [ + 0.328125, + 0.0 + ], + [ + 0.3203125, + 0.0 + ], + [ + 0.3125, + 0.0 + ], + [ + 0.3046875, + 0.0 + ], + [ + 0.296875, + 0.0 + ], + [ + 0.2890625, + 0.0 + ], + [ + 0.28125, + 0.0 + ], + [ + 0.2734375, + 0.0 + ], + [ + 0.265625, + 0.0 + ], + [ + 0.2578125, + 0.0 + ], + [ + 0.25, + 0.0 + ], + [ + 0.2421875, + 0.0 + ] + ] + ], + "15": [ + [ + [ + 0.4609375, + 0.53125 + ], + [ + 0.4609375, + 0.5390625 + ], + [ + 0.453125, + 0.546875 + ], + [ + 0.453125, + 0.5546875 + ], + [ + 0.4453125, + 0.5625 + ], + [ + 0.4453125, + 0.5703125 + ], + [ + 0.4375, + 0.578125 + ], + [ + 0.4296875, + 0.5859375 + ], + [ + 0.4296875, + 0.59375 + ], + [ + 0.421875, + 0.6015625 + ], + [ + 0.421875, + 0.609375 + ], + [ + 0.4140625, + 0.6171875 + ], + [ + 0.40625, + 0.625 + ], + [ + 0.40625, + 0.6328125 + ], + [ + 0.3984375, + 0.640625 + ], + [ + 0.3984375, + 0.6484375 + ], + [ + 0.390625, + 0.65625 + ], + [ + 0.390625, + 0.6640625 + ], + [ + 0.3828125, + 0.671875 + ], + [ + 0.375, + 0.6796875 + ], + [ + 0.375, + 0.6875 + ], + [ + 0.3671875, + 0.6953125 + ], + [ + 0.3671875, + 0.703125 + ], + [ + 0.359375, + 0.7109375 + ], + [ + 0.359375, + 0.71875 + ], + [ + 0.359375, + 0.7265625 + ], + [ + 0.3671875, + 0.734375 + ], + [ + 0.3671875, + 0.7421875 + ], + [ + 0.375, + 0.75 + ], + [ + 0.375, + 0.7578125 + ], + [ + 0.3828125, + 0.765625 + ], + [ + 0.390625, + 0.7734375 + ], + [ + 0.390625, + 0.78125 + ], + [ + 0.3984375, + 0.7890625 + ], + [ + 0.3984375, + 0.796875 + ], + [ + 0.40625, + 0.8046875 + ], + [ + 0.4140625, + 0.8125 + ], + [ + 0.4140625, + 0.8203125 + ], + [ + 0.421875, + 0.828125 + ], + [ + 0.421875, + 0.8359375 + ], + [ + 0.4296875, + 0.84375 + ], + [ + 0.4296875, + 0.8515625 + ], + [ + 0.4375, + 0.859375 + ], + [ + 0.4453125, + 0.8671875 + ], + [ + 0.4453125, + 0.875 + ], + [ + 0.453125, + 0.8828125 + ], + [ + 0.453125, + 0.890625 + ], + [ + 0.4609375, + 0.8984375 + ], + [ + 0.46875, + 0.8984375 + ], + [ + 0.4765625, + 0.8984375 + ], + [ + 0.484375, + 0.8984375 + ], + [ + 0.4921875, + 0.8984375 + ], + [ + 0.5, + 0.8984375 + ], + [ + 0.5078125, + 0.8984375 + ], + [ + 0.515625, + 0.8984375 + ], + [ + 0.5234375, + 0.8984375 + ], + [ + 0.53125, + 0.8984375 + ], + [ + 0.5390625, + 0.8984375 + ], + [ + 0.546875, + 0.8984375 + ], + [ + 0.5546875, + 0.8984375 + ], + [ + 0.5625, + 0.8984375 + ], + [ + 0.5703125, + 0.8984375 + ], + [ + 0.578125, + 0.8984375 + ], + [ + 0.5859375, + 0.8984375 + ], + [ + 0.59375, + 0.8984375 + ], + [ + 0.6015625, + 0.8984375 + ], + [ + 0.609375, + 0.8984375 + ], + [ + 0.6171875, + 0.8984375 + ], + [ + 0.625, + 0.8984375 + ], + [ + 0.6328125, + 0.8984375 + ], + [ + 0.640625, + 0.8984375 + ], + [ + 0.6484375, + 0.8984375 + ], + [ + 0.65625, + 0.8984375 + ], + [ + 0.6640625, + 0.8984375 + ], + [ + 0.671875, + 0.8984375 + ], + [ + 0.6796875, + 0.8984375 + ], + [ + 0.6875, + 0.8984375 + ], + [ + 0.6953125, + 0.890625 + ], + [ + 0.6953125, + 0.8828125 + ], + [ + 0.703125, + 0.875 + ], + [ + 0.7109375, + 0.8671875 + ], + [ + 0.7109375, + 0.859375 + ], + [ + 0.71875, + 0.8515625 + ], + [ + 0.71875, + 0.84375 + ], + [ + 0.7265625, + 0.8359375 + ], + [ + 0.734375, + 0.828125 + ], + [ + 0.734375, + 0.8203125 + ], + [ + 0.7421875, + 0.8125 + ], + [ + 0.75, + 0.8046875 + ], + [ + 0.75, + 0.796875 + ], + [ + 0.7578125, + 0.7890625 + ], + [ + 0.7578125, + 0.78125 + ], + [ + 0.765625, + 0.7734375 + ], + [ + 0.7734375, + 0.765625 + ], + [ + 0.7734375, + 0.7578125 + ], + [ + 0.78125, + 0.75 + ], + [ + 0.7890625, + 0.7421875 + ], + [ + 0.7890625, + 0.734375 + ], + [ + 0.796875, + 0.7265625 + ], + [ + 0.796875, + 0.71875 + ], + [ + 0.796875, + 0.7109375 + ], + [ + 0.7890625, + 0.703125 + ], + [ + 0.7890625, + 0.6953125 + ], + [ + 0.78125, + 0.6875 + ], + [ + 0.7734375, + 0.6796875 + ], + [ + 0.7734375, + 0.671875 + ], + [ + 0.765625, + 0.6640625 + ], + [ + 0.765625, + 0.65625 + ], + [ + 0.7578125, + 0.6484375 + ], + [ + 0.75, + 0.640625 + ], + [ + 0.75, + 0.6328125 + ], + [ + 0.7421875, + 0.625 + ], + [ + 0.734375, + 0.6171875 + ], + [ + 0.734375, + 0.609375 + ], + [ + 0.7265625, + 0.6015625 + ], + [ + 0.7265625, + 0.59375 + ], + [ + 0.71875, + 0.5859375 + ], + [ + 0.7109375, + 0.578125 + ], + [ + 0.7109375, + 0.5703125 + ], + [ + 0.703125, + 0.5625 + ], + [ + 0.6953125, + 0.5546875 + ], + [ + 0.6953125, + 0.546875 + ], + [ + 0.6875, + 0.5390625 + ], + [ + 0.6875, + 0.53125 + ], + [ + 0.6796875, + 0.53125 + ], + [ + 0.671875, + 0.53125 + ], + [ + 0.6640625, + 0.53125 + ], + [ + 0.65625, + 0.53125 + ], + [ + 0.6484375, + 0.53125 + ], + [ + 0.640625, + 0.53125 + ], + [ + 0.6328125, + 0.53125 + ], + [ + 0.625, + 0.53125 + ], + [ + 0.6171875, + 0.53125 + ], + [ + 0.609375, + 0.53125 + ], + [ + 0.6015625, + 0.53125 + ], + [ + 0.59375, + 0.53125 + ], + [ + 0.5859375, + 0.53125 + ], + [ + 0.578125, + 0.53125 + ], + [ + 0.5703125, + 0.53125 + ], + [ + 0.5625, + 0.53125 + ], + [ + 0.5546875, + 0.53125 + ], + [ + 0.546875, + 0.53125 + ], + [ + 0.5390625, + 0.53125 + ], + [ + 0.53125, + 0.53125 + ], + [ + 0.5234375, + 0.53125 + ], + [ + 0.515625, + 0.53125 + ], + [ + 0.5078125, + 0.53125 + ], + [ + 0.5, + 0.53125 + ], + [ + 0.4921875, + 0.53125 + ], + [ + 0.484375, + 0.53125 + ], + [ + 0.4765625, + 0.53125 + ], + [ + 0.46875, + 0.53125 + ] + ], + [ + [ + 0.734375, + 0.0 + ], + [ + 0.734375, + 0.0078125 + ], + [ + 0.7265625, + 0.015625 + ], + [ + 0.7265625, + 0.0234375 + ], + [ + 0.71875, + 0.03125 + ], + [ + 0.71875, + 0.0390625 + ], + [ + 0.7109375, + 0.046875 + ], + [ + 0.703125, + 0.0546875 + ], + [ + 0.703125, + 0.0625 + ], + [ + 0.6953125, + 0.0703125 + ], + [ + 0.6953125, + 0.078125 + ], + [ + 0.6875, + 0.0859375 + ], + [ + 0.6875, + 0.09375 + ], + [ + 0.6796875, + 0.1015625 + ], + [ + 0.671875, + 0.109375 + ], + [ + 0.671875, + 0.1171875 + ], + [ + 0.6640625, + 0.125 + ], + [ + 0.6640625, + 0.1328125 + ], + [ + 0.65625, + 0.140625 + ], + [ + 0.65625, + 0.1484375 + ], + [ + 0.65625, + 0.15625 + ], + [ + 0.6640625, + 0.1640625 + ], + [ + 0.6640625, + 0.171875 + ], + [ + 0.671875, + 0.1796875 + ], + [ + 0.671875, + 0.1875 + ], + [ + 0.6796875, + 0.1953125 + ], + [ + 0.6875, + 0.203125 + ], + [ + 0.6875, + 0.2109375 + ], + [ + 0.6953125, + 0.21875 + ], + [ + 0.6953125, + 0.2265625 + ], + [ + 0.703125, + 0.234375 + ], + [ + 0.703125, + 0.2421875 + ], + [ + 0.7109375, + 0.25 + ], + [ + 0.71875, + 0.2578125 + ], + [ + 0.71875, + 0.265625 + ], + [ + 0.7265625, + 0.2734375 + ], + [ + 0.7265625, + 0.28125 + ], + [ + 0.734375, + 0.2890625 + ], + [ + 0.7421875, + 0.2890625 + ], + [ + 0.75, + 0.2890625 + ], + [ + 0.7578125, + 0.2890625 + ], + [ + 0.765625, + 0.2890625 + ], + [ + 0.7734375, + 0.2890625 + ], + [ + 0.78125, + 0.2890625 + ], + [ + 0.7890625, + 0.2890625 + ], + [ + 0.796875, + 0.2890625 + ], + [ + 0.8046875, + 0.2890625 + ], + [ + 0.8125, + 0.2890625 + ], + [ + 0.8203125, + 0.2890625 + ], + [ + 0.828125, + 0.2890625 + ], + [ + 0.8359375, + 0.2890625 + ], + [ + 0.84375, + 0.2890625 + ], + [ + 0.8515625, + 0.2890625 + ], + [ + 0.859375, + 0.2890625 + ], + [ + 0.8671875, + 0.2890625 + ], + [ + 0.875, + 0.2890625 + ], + [ + 0.8828125, + 0.2890625 + ], + [ + 0.890625, + 0.2890625 + ], + [ + 0.8984375, + 0.2890625 + ], + [ + 0.90625, + 0.2890625 + ], + [ + 0.9140625, + 0.28125 + ], + [ + 0.9140625, + 0.2734375 + ], + [ + 0.921875, + 0.265625 + ], + [ + 0.921875, + 0.2578125 + ], + [ + 0.9296875, + 0.25 + ], + [ + 0.9375, + 0.2421875 + ], + [ + 0.9375, + 0.234375 + ], + [ + 0.9453125, + 0.2265625 + ], + [ + 0.9453125, + 0.21875 + ], + [ + 0.953125, + 0.2109375 + ], + [ + 0.953125, + 0.203125 + ], + [ + 0.9609375, + 0.1953125 + ], + [ + 0.96875, + 0.1875 + ], + [ + 0.96875, + 0.1796875 + ], + [ + 0.9765625, + 0.171875 + ], + [ + 0.9765625, + 0.1640625 + ], + [ + 0.984375, + 0.15625 + ], + [ + 0.984375, + 0.1484375 + ], + [ + 0.984375, + 0.140625 + ], + [ + 0.9765625, + 0.1328125 + ], + [ + 0.9765625, + 0.125 + ], + [ + 0.96875, + 0.1171875 + ], + [ + 0.96875, + 0.109375 + ], + [ + 0.9609375, + 0.1015625 + ], + [ + 0.953125, + 0.09375 + ], + [ + 0.953125, + 0.0859375 + ], + [ + 0.9453125, + 0.078125 + ], + [ + 0.9453125, + 0.0703125 + ], + [ + 0.9375, + 0.0625 + ], + [ + 0.9375, + 0.0546875 + ], + [ + 0.9296875, + 0.046875 + ], + [ + 0.921875, + 0.0390625 + ], + [ + 0.921875, + 0.03125 + ], + [ + 0.9140625, + 0.0234375 + ], + [ + 0.9140625, + 0.015625 + ], + [ + 0.90625, + 0.0078125 + ], + [ + 0.90625, + 0.0 + ], + [ + 0.8984375, + 0.0 + ], + [ + 0.890625, + 0.0 + ], + [ + 0.8828125, + 0.0 + ], + [ + 0.875, + 0.0 + ], + [ + 0.8671875, + 0.0 + ], + [ + 0.859375, + 0.0 + ], + [ + 0.8515625, + 0.0 + ], + [ + 0.84375, + 0.0 + ], + [ + 0.8359375, + 0.0 + ], + [ + 0.828125, + 0.0 + ], + [ + 0.8203125, + 0.0 + ], + [ + 0.8125, + 0.0 + ], + [ + 0.8046875, + 0.0 + ], + [ + 0.796875, + 0.0 + ], + [ + 0.7890625, + 0.0 + ], + [ + 0.78125, + 0.0 + ], + [ + 0.7734375, + 0.0 + ], + [ + 0.765625, + 0.0 + ], + [ + 0.7578125, + 0.0 + ], + [ + 0.75, + 0.0 + ], + [ + 0.7421875, + 0.0 + ] + ] + ], + "16": [ + [ + [ + 0.171875, + 0.0 + ], + [ + 0.171875, + 0.0078125 + ], + [ + 0.1640625, + 0.015625 + ], + [ + 0.1640625, + 0.0234375 + ], + [ + 0.15625, + 0.03125 + ], + [ + 0.15625, + 0.0390625 + ], + [ + 0.1484375, + 0.046875 + ], + [ + 0.140625, + 0.0546875 + ], + [ + 0.140625, + 0.0625 + ], + [ + 0.1328125, + 0.0703125 + ], + [ + 0.1328125, + 0.078125 + ], + [ + 0.125, + 0.0859375 + ], + [ + 0.125, + 0.09375 + ], + [ + 0.1171875, + 0.1015625 + ], + [ + 0.109375, + 0.109375 + ], + [ + 0.109375, + 0.1171875 + ], + [ + 0.1015625, + 0.125 + ], + [ + 0.1015625, + 0.1328125 + ], + [ + 0.09375, + 0.140625 + ], + [ + 0.0859375, + 0.1484375 + ], + [ + 0.0859375, + 0.15625 + ], + [ + 0.078125, + 0.1640625 + ], + [ + 0.078125, + 0.171875 + ], + [ + 0.0703125, + 0.1796875 + ], + [ + 0.0703125, + 0.1875 + ], + [ + 0.0625, + 0.1953125 + ], + [ + 0.0546875, + 0.203125 + ], + [ + 0.0546875, + 0.2109375 + ], + [ + 0.046875, + 0.21875 + ], + [ + 0.046875, + 0.2265625 + ], + [ + 0.0390625, + 0.234375 + ], + [ + 0.0390625, + 0.2421875 + ], + [ + 0.03125, + 0.25 + ], + [ + 0.0234375, + 0.2578125 + ], + [ + 0.0234375, + 0.265625 + ], + [ + 0.015625, + 0.2734375 + ], + [ + 0.015625, + 0.28125 + ], + [ + 0.0078125, + 0.2890625 + ], + [ + 0.0078125, + 0.296875 + ], + [ + 0.0078125, + 0.3046875 + ], + [ + 0.015625, + 0.3125 + ], + [ + 0.015625, + 0.3203125 + ], + [ + 0.0234375, + 0.328125 + ], + [ + 0.0234375, + 0.3359375 + ], + [ + 0.03125, + 0.34375 + ], + [ + 0.0390625, + 0.3515625 + ], + [ + 0.0390625, + 0.359375 + ], + [ + 0.046875, + 0.3671875 + ], + [ + 0.046875, + 0.375 + ], + [ + 0.0546875, + 0.3828125 + ], + [ + 0.0546875, + 0.390625 + ], + [ + 0.0625, + 0.3984375 + ], + [ + 0.0703125, + 0.40625 + ], + [ + 0.0703125, + 0.4140625 + ], + [ + 0.078125, + 0.421875 + ], + [ + 0.078125, + 0.4296875 + ], + [ + 0.0859375, + 0.4375 + ], + [ + 0.09375, + 0.4453125 + ], + [ + 0.09375, + 0.453125 + ], + [ + 0.1015625, + 0.4609375 + ], + [ + 0.1015625, + 0.46875 + ], + [ + 0.09375, + 0.4765625 + ], + [ + 0.09375, + 0.484375 + ], + [ + 0.0859375, + 0.4921875 + ], + [ + 0.0859375, + 0.5 + ], + [ + 0.078125, + 0.5078125 + ], + [ + 0.0703125, + 0.515625 + ], + [ + 0.0703125, + 0.5234375 + ], + [ + 0.0625, + 0.53125 + ], + [ + 0.0625, + 0.5390625 + ], + [ + 0.0546875, + 0.546875 + ], + [ + 0.046875, + 0.5546875 + ], + [ + 0.046875, + 0.5625 + ], + [ + 0.0390625, + 0.5703125 + ], + [ + 0.0390625, + 0.578125 + ], + [ + 0.03125, + 0.5859375 + ], + [ + 0.0234375, + 0.59375 + ], + [ + 0.0234375, + 0.6015625 + ], + [ + 0.015625, + 0.609375 + ], + [ + 0.015625, + 0.6171875 + ], + [ + 0.0078125, + 0.625 + ], + [ + 0.0078125, + 0.6328125 + ], + [ + 0.0078125, + 0.640625 + ], + [ + 0.015625, + 0.6484375 + ], + [ + 0.015625, + 0.65625 + ], + [ + 0.0234375, + 0.6640625 + ], + [ + 0.0234375, + 0.671875 + ], + [ + 0.03125, + 0.6796875 + ], + [ + 0.0390625, + 0.6875 + ], + [ + 0.0390625, + 0.6953125 + ], + [ + 0.046875, + 0.703125 + ], + [ + 0.046875, + 0.7109375 + ], + [ + 0.0546875, + 0.71875 + ], + [ + 0.0546875, + 0.7265625 + ], + [ + 0.0625, + 0.734375 + ], + [ + 0.0703125, + 0.7421875 + ], + [ + 0.0703125, + 0.75 + ], + [ + 0.078125, + 0.7578125 + ], + [ + 0.078125, + 0.765625 + ], + [ + 0.0859375, + 0.7734375 + ], + [ + 0.0859375, + 0.78125 + ], + [ + 0.09375, + 0.7890625 + ], + [ + 0.1015625, + 0.796875 + ], + [ + 0.1015625, + 0.8046875 + ], + [ + 0.109375, + 0.8125 + ], + [ + 0.109375, + 0.8203125 + ], + [ + 0.1171875, + 0.828125 + ], + [ + 0.1171875, + 0.8359375 + ], + [ + 0.125, + 0.84375 + ], + [ + 0.1328125, + 0.8515625 + ], + [ + 0.1328125, + 0.859375 + ], + [ + 0.140625, + 0.8671875 + ], + [ + 0.140625, + 0.875 + ], + [ + 0.1484375, + 0.8828125 + ], + [ + 0.15625, + 0.8828125 + ], + [ + 0.1640625, + 0.8828125 + ], + [ + 0.171875, + 0.8828125 + ], + [ + 0.1796875, + 0.8828125 + ], + [ + 0.1875, + 0.8828125 + ], + [ + 0.1953125, + 0.8828125 + ], + [ + 0.203125, + 0.8828125 + ], + [ + 0.2109375, + 0.8828125 + ], + [ + 0.21875, + 0.8828125 + ], + [ + 0.2265625, + 0.8828125 + ], + [ + 0.234375, + 0.8828125 + ], + [ + 0.2421875, + 0.8828125 + ], + [ + 0.25, + 0.8828125 + ], + [ + 0.2578125, + 0.8828125 + ], + [ + 0.265625, + 0.8828125 + ], + [ + 0.2734375, + 0.8828125 + ], + [ + 0.28125, + 0.8828125 + ], + [ + 0.2890625, + 0.8828125 + ], + [ + 0.296875, + 0.8828125 + ], + [ + 0.3046875, + 0.8828125 + ], + [ + 0.3125, + 0.8828125 + ], + [ + 0.3203125, + 0.8828125 + ], + [ + 0.328125, + 0.8828125 + ], + [ + 0.3359375, + 0.8828125 + ], + [ + 0.34375, + 0.8828125 + ], + [ + 0.3515625, + 0.8828125 + ], + [ + 0.359375, + 0.8828125 + ], + [ + 0.3671875, + 0.8828125 + ], + [ + 0.375, + 0.8828125 + ], + [ + 0.3828125, + 0.8828125 + ], + [ + 0.390625, + 0.8828125 + ], + [ + 0.3984375, + 0.8828125 + ], + [ + 0.40625, + 0.8828125 + ], + [ + 0.4140625, + 0.8828125 + ], + [ + 0.421875, + 0.8828125 + ], + [ + 0.4296875, + 0.8828125 + ], + [ + 0.4375, + 0.8828125 + ], + [ + 0.4453125, + 0.8828125 + ], + [ + 0.453125, + 0.8828125 + ], + [ + 0.4609375, + 0.875 + ], + [ + 0.4609375, + 0.8671875 + ], + [ + 0.46875, + 0.859375 + ], + [ + 0.4765625, + 0.8515625 + ], + [ + 0.484375, + 0.84375 + ], + [ + 0.4921875, + 0.8515625 + ], + [ + 0.4921875, + 0.859375 + ], + [ + 0.5, + 0.8671875 + ], + [ + 0.5, + 0.875 + ], + [ + 0.5078125, + 0.8828125 + ], + [ + 0.515625, + 0.8828125 + ], + [ + 0.5234375, + 0.8828125 + ], + [ + 0.53125, + 0.8828125 + ], + [ + 0.5390625, + 0.8828125 + ], + [ + 0.546875, + 0.8828125 + ], + [ + 0.5546875, + 0.8828125 + ], + [ + 0.5625, + 0.8828125 + ], + [ + 0.5703125, + 0.8828125 + ], + [ + 0.578125, + 0.8828125 + ], + [ + 0.5859375, + 0.8828125 + ], + [ + 0.59375, + 0.8828125 + ], + [ + 0.6015625, + 0.8828125 + ], + [ + 0.609375, + 0.8828125 + ], + [ + 0.6171875, + 0.8828125 + ], + [ + 0.625, + 0.8828125 + ], + [ + 0.6328125, + 0.8828125 + ], + [ + 0.640625, + 0.8828125 + ], + [ + 0.6484375, + 0.8828125 + ], + [ + 0.65625, + 0.8828125 + ], + [ + 0.6640625, + 0.8828125 + ], + [ + 0.671875, + 0.8828125 + ], + [ + 0.6796875, + 0.8828125 + ], + [ + 0.6875, + 0.8828125 + ], + [ + 0.6953125, + 0.8828125 + ], + [ + 0.703125, + 0.8828125 + ], + [ + 0.7109375, + 0.8828125 + ], + [ + 0.71875, + 0.8828125 + ], + [ + 0.7265625, + 0.8828125 + ], + [ + 0.734375, + 0.8828125 + ], + [ + 0.7421875, + 0.8828125 + ], + [ + 0.75, + 0.8828125 + ], + [ + 0.7578125, + 0.8828125 + ], + [ + 0.765625, + 0.8828125 + ], + [ + 0.7734375, + 0.8828125 + ], + [ + 0.78125, + 0.8828125 + ], + [ + 0.7890625, + 0.8828125 + ], + [ + 0.796875, + 0.8828125 + ], + [ + 0.8046875, + 0.8828125 + ], + [ + 0.8125, + 0.8828125 + ], + [ + 0.8203125, + 0.8828125 + ], + [ + 0.828125, + 0.8828125 + ], + [ + 0.8359375, + 0.875 + ], + [ + 0.8359375, + 0.8671875 + ], + [ + 0.84375, + 0.859375 + ], + [ + 0.84375, + 0.8515625 + ], + [ + 0.8515625, + 0.84375 + ], + [ + 0.859375, + 0.8359375 + ], + [ + 0.859375, + 0.828125 + ], + [ + 0.8671875, + 0.8203125 + ], + [ + 0.8671875, + 0.8125 + ], + [ + 0.875, + 0.8046875 + ], + [ + 0.8828125, + 0.796875 + ], + [ + 0.8828125, + 0.7890625 + ], + [ + 0.890625, + 0.78125 + ], + [ + 0.890625, + 0.7734375 + ], + [ + 0.8984375, + 0.765625 + ], + [ + 0.90625, + 0.7578125 + ], + [ + 0.90625, + 0.75 + ], + [ + 0.9140625, + 0.7421875 + ], + [ + 0.9140625, + 0.734375 + ], + [ + 0.921875, + 0.7265625 + ], + [ + 0.9296875, + 0.71875 + ], + [ + 0.9296875, + 0.7109375 + ], + [ + 0.9375, + 0.703125 + ], + [ + 0.9375, + 0.6953125 + ], + [ + 0.9453125, + 0.6875 + ], + [ + 0.953125, + 0.6796875 + ], + [ + 0.953125, + 0.671875 + ], + [ + 0.9609375, + 0.6640625 + ], + [ + 0.9609375, + 0.65625 + ], + [ + 0.96875, + 0.6484375 + ], + [ + 0.9765625, + 0.640625 + ], + [ + 0.9765625, + 0.6328125 + ], + [ + 0.984375, + 0.625 + ], + [ + 0.984375, + 0.6171875 + ], + [ + 0.984375, + 0.609375 + ], + [ + 0.9765625, + 0.6015625 + ], + [ + 0.9765625, + 0.59375 + ], + [ + 0.96875, + 0.5859375 + ], + [ + 0.9609375, + 0.578125 + ], + [ + 0.9609375, + 0.5703125 + ], + [ + 0.953125, + 0.5625 + ], + [ + 0.953125, + 0.5546875 + ], + [ + 0.9453125, + 0.546875 + ], + [ + 0.9375, + 0.5390625 + ], + [ + 0.9375, + 0.53125 + ], + [ + 0.9296875, + 0.5234375 + ], + [ + 0.921875, + 0.515625 + ], + [ + 0.921875, + 0.5078125 + ], + [ + 0.9140625, + 0.5 + ], + [ + 0.9140625, + 0.4921875 + ], + [ + 0.90625, + 0.484375 + ], + [ + 0.8984375, + 0.4765625 + ], + [ + 0.8984375, + 0.46875 + ], + [ + 0.890625, + 0.4609375 + ], + [ + 0.890625, + 0.453125 + ], + [ + 0.8828125, + 0.4453125 + ], + [ + 0.875, + 0.4375 + ], + [ + 0.875, + 0.4296875 + ], + [ + 0.8671875, + 0.421875 + ], + [ + 0.859375, + 0.4140625 + ], + [ + 0.859375, + 0.40625 + ], + [ + 0.8515625, + 0.3984375 + ], + [ + 0.8515625, + 0.390625 + ], + [ + 0.84375, + 0.3828125 + ], + [ + 0.8359375, + 0.375 + ], + [ + 0.8359375, + 0.3671875 + ], + [ + 0.828125, + 0.359375 + ], + [ + 0.828125, + 0.3515625 + ], + [ + 0.8203125, + 0.3515625 + ], + [ + 0.8125, + 0.3515625 + ], + [ + 0.8046875, + 0.3515625 + ], + [ + 0.796875, + 0.3515625 + ], + [ + 0.7890625, + 0.3515625 + ], + [ + 0.78125, + 0.3515625 + ], + [ + 0.7734375, + 0.3515625 + ], + [ + 0.765625, + 0.3515625 + ], + [ + 0.7578125, + 0.3515625 + ], + [ + 0.75, + 0.3515625 + ], + [ + 0.7421875, + 0.3515625 + ], + [ + 0.734375, + 0.3515625 + ], + [ + 0.7265625, + 0.3515625 + ], + [ + 0.71875, + 0.3515625 + ], + [ + 0.7109375, + 0.3515625 + ], + [ + 0.703125, + 0.3515625 + ], + [ + 0.6953125, + 0.3515625 + ], + [ + 0.6875, + 0.3515625 + ], + [ + 0.6796875, + 0.3515625 + ], + [ + 0.671875, + 0.34375 + ], + [ + 0.671875, + 0.3359375 + ], + [ + 0.6796875, + 0.328125 + ], + [ + 0.6875, + 0.3203125 + ], + [ + 0.6875, + 0.3125 + ], + [ + 0.6953125, + 0.3046875 + ], + [ + 0.6953125, + 0.296875 + ], + [ + 0.6953125, + 0.2890625 + ], + [ + 0.6875, + 0.28125 + ], + [ + 0.6875, + 0.2734375 + ], + [ + 0.6796875, + 0.265625 + ], + [ + 0.671875, + 0.2578125 + ], + [ + 0.671875, + 0.25 + ], + [ + 0.6640625, + 0.2421875 + ], + [ + 0.6640625, + 0.234375 + ], + [ + 0.65625, + 0.2265625 + ], + [ + 0.6484375, + 0.21875 + ], + [ + 0.6484375, + 0.2109375 + ], + [ + 0.640625, + 0.203125 + ], + [ + 0.640625, + 0.1953125 + ], + [ + 0.6328125, + 0.1875 + ], + [ + 0.625, + 0.1796875 + ], + [ + 0.625, + 0.171875 + ], + [ + 0.6171875, + 0.1640625 + ], + [ + 0.6171875, + 0.15625 + ], + [ + 0.609375, + 0.1484375 + ], + [ + 0.6015625, + 0.140625 + ], + [ + 0.6015625, + 0.1328125 + ], + [ + 0.59375, + 0.125 + ], + [ + 0.59375, + 0.1171875 + ], + [ + 0.5859375, + 0.109375 + ], + [ + 0.578125, + 0.1015625 + ], + [ + 0.578125, + 0.09375 + ], + [ + 0.5703125, + 0.0859375 + ], + [ + 0.5703125, + 0.078125 + ], + [ + 0.5625, + 0.0703125 + ], + [ + 0.5546875, + 0.0625 + ], + [ + 0.5546875, + 0.0546875 + ], + [ + 0.546875, + 0.046875 + ], + [ + 0.546875, + 0.0390625 + ], + [ + 0.5390625, + 0.03125 + ], + [ + 0.53125, + 0.0234375 + ], + [ + 0.53125, + 0.015625 + ], + [ + 0.5234375, + 0.0078125 + ], + [ + 0.5234375, + 0.0 + ], + [ + 0.515625, + 0.0 + ], + [ + 0.5078125, + 0.0 + ], + [ + 0.5, + 0.0 + ], + [ + 0.4921875, + 0.0 + ], + [ + 0.484375, + 0.0 + ], + [ + 0.4765625, + 0.0 + ], + [ + 0.46875, + 0.0 + ], + [ + 0.4609375, + 0.0 + ], + [ + 0.453125, + 0.0 + ], + [ + 0.4453125, + 0.0 + ], + [ + 0.4375, + 0.0 + ], + [ + 0.4296875, + 0.0 + ], + [ + 0.421875, + 0.0 + ], + [ + 0.4140625, + 0.0 + ], + [ + 0.40625, + 0.0 + ], + [ + 0.3984375, + 0.0 + ], + [ + 0.390625, + 0.0 + ], + [ + 0.3828125, + 0.0 + ], + [ + 0.375, + 0.0 + ], + [ + 0.3671875, + 0.0 + ], + [ + 0.359375, + 0.0 + ], + [ + 0.3515625, + 0.0 + ], + [ + 0.34375, + 0.0 + ], + [ + 0.3359375, + 0.0 + ], + [ + 0.328125, + 0.0 + ], + [ + 0.3203125, + 0.0 + ], + [ + 0.3125, + 0.0 + ], + [ + 0.3046875, + 0.0 + ], + [ + 0.296875, + 0.0 + ], + [ + 0.2890625, + 0.0 + ], + [ + 0.28125, + 0.0 + ], + [ + 0.2734375, + 0.0 + ], + [ + 0.265625, + 0.0 + ], + [ + 0.2578125, + 0.0 + ], + [ + 0.25, + 0.0 + ], + [ + 0.2421875, + 0.0 + ], + [ + 0.234375, + 0.0 + ], + [ + 0.2265625, + 0.0 + ], + [ + 0.21875, + 0.0 + ], + [ + 0.2109375, + 0.0 + ], + [ + 0.203125, + 0.0 + ], + [ + 0.1953125, + 0.0 + ], + [ + 0.1875, + 0.0 + ], + [ + 0.1796875, + 0.0 + ] + ] + ], + "17": [ + [ + [ + 0.40625, + 0.0 + ], + [ + 0.40625, + 0.0078125 + ], + [ + 0.3984375, + 0.015625 + ], + [ + 0.3984375, + 0.0234375 + ], + [ + 0.390625, + 0.03125 + ], + [ + 0.390625, + 0.0390625 + ], + [ + 0.3828125, + 0.046875 + ], + [ + 0.375, + 0.0546875 + ], + [ + 0.375, + 0.0625 + ], + [ + 0.3671875, + 0.0703125 + ], + [ + 0.3671875, + 0.078125 + ], + [ + 0.359375, + 0.0859375 + ], + [ + 0.359375, + 0.09375 + ], + [ + 0.3515625, + 0.1015625 + ], + [ + 0.34375, + 0.109375 + ], + [ + 0.34375, + 0.1171875 + ], + [ + 0.3359375, + 0.125 + ], + [ + 0.3359375, + 0.1328125 + ], + [ + 0.328125, + 0.140625 + ], + [ + 0.3203125, + 0.1484375 + ], + [ + 0.3203125, + 0.15625 + ], + [ + 0.3125, + 0.1640625 + ], + [ + 0.3125, + 0.171875 + ], + [ + 0.3046875, + 0.1796875 + ], + [ + 0.3046875, + 0.1875 + ], + [ + 0.296875, + 0.1953125 + ], + [ + 0.2890625, + 0.203125 + ], + [ + 0.2890625, + 0.2109375 + ], + [ + 0.28125, + 0.21875 + ], + [ + 0.28125, + 0.2265625 + ], + [ + 0.2734375, + 0.234375 + ], + [ + 0.265625, + 0.2421875 + ], + [ + 0.265625, + 0.25 + ], + [ + 0.2578125, + 0.2578125 + ], + [ + 0.2578125, + 0.265625 + ], + [ + 0.25, + 0.2734375 + ], + [ + 0.25, + 0.28125 + ], + [ + 0.2421875, + 0.2890625 + ], + [ + 0.234375, + 0.296875 + ], + [ + 0.234375, + 0.3046875 + ], + [ + 0.2265625, + 0.3125 + ], + [ + 0.2265625, + 0.3203125 + ], + [ + 0.21875, + 0.328125 + ], + [ + 0.21875, + 0.3359375 + ], + [ + 0.21875, + 0.34375 + ], + [ + 0.2265625, + 0.3515625 + ], + [ + 0.2265625, + 0.359375 + ], + [ + 0.234375, + 0.3671875 + ], + [ + 0.234375, + 0.375 + ], + [ + 0.2421875, + 0.3828125 + ], + [ + 0.25, + 0.390625 + ], + [ + 0.25, + 0.3984375 + ], + [ + 0.2578125, + 0.40625 + ], + [ + 0.2578125, + 0.4140625 + ], + [ + 0.265625, + 0.421875 + ], + [ + 0.2578125, + 0.4296875 + ], + [ + 0.25, + 0.4375 + ], + [ + 0.25, + 0.4453125 + ], + [ + 0.2421875, + 0.453125 + ], + [ + 0.2421875, + 0.4609375 + ], + [ + 0.234375, + 0.46875 + ], + [ + 0.234375, + 0.4765625 + ], + [ + 0.2265625, + 0.484375 + ], + [ + 0.21875, + 0.4921875 + ], + [ + 0.21875, + 0.5 + ], + [ + 0.2109375, + 0.5078125 + ], + [ + 0.2109375, + 0.515625 + ], + [ + 0.203125, + 0.5234375 + ], + [ + 0.203125, + 0.53125 + ], + [ + 0.203125, + 0.5390625 + ], + [ + 0.2109375, + 0.546875 + ], + [ + 0.2109375, + 0.5546875 + ], + [ + 0.21875, + 0.5625 + ], + [ + 0.21875, + 0.5703125 + ], + [ + 0.2265625, + 0.578125 + ], + [ + 0.234375, + 0.5859375 + ], + [ + 0.234375, + 0.59375 + ], + [ + 0.2421875, + 0.6015625 + ], + [ + 0.2421875, + 0.609375 + ], + [ + 0.25, + 0.6171875 + ], + [ + 0.25, + 0.625 + ], + [ + 0.2578125, + 0.6328125 + ], + [ + 0.265625, + 0.640625 + ], + [ + 0.265625, + 0.6484375 + ], + [ + 0.2734375, + 0.65625 + ], + [ + 0.2734375, + 0.6640625 + ], + [ + 0.28125, + 0.671875 + ], + [ + 0.2890625, + 0.6796875 + ], + [ + 0.2890625, + 0.6875 + ], + [ + 0.296875, + 0.6953125 + ], + [ + 0.296875, + 0.703125 + ], + [ + 0.3046875, + 0.7109375 + ], + [ + 0.3046875, + 0.71875 + ], + [ + 0.3125, + 0.7265625 + ], + [ + 0.3203125, + 0.734375 + ], + [ + 0.3203125, + 0.7421875 + ], + [ + 0.328125, + 0.75 + ], + [ + 0.328125, + 0.7578125 + ], + [ + 0.3359375, + 0.765625 + ], + [ + 0.34375, + 0.7734375 + ], + [ + 0.34375, + 0.78125 + ], + [ + 0.3515625, + 0.7890625 + ], + [ + 0.3515625, + 0.796875 + ], + [ + 0.359375, + 0.8046875 + ], + [ + 0.359375, + 0.8125 + ], + [ + 0.3671875, + 0.8203125 + ], + [ + 0.375, + 0.828125 + ], + [ + 0.375, + 0.8359375 + ], + [ + 0.3828125, + 0.84375 + ], + [ + 0.3828125, + 0.8515625 + ], + [ + 0.390625, + 0.859375 + ], + [ + 0.3984375, + 0.859375 + ], + [ + 0.40625, + 0.859375 + ], + [ + 0.4140625, + 0.859375 + ], + [ + 0.421875, + 0.859375 + ], + [ + 0.4296875, + 0.859375 + ], + [ + 0.4375, + 0.859375 + ], + [ + 0.4453125, + 0.859375 + ], + [ + 0.453125, + 0.859375 + ], + [ + 0.4609375, + 0.859375 + ], + [ + 0.46875, + 0.859375 + ], + [ + 0.4765625, + 0.859375 + ], + [ + 0.484375, + 0.859375 + ], + [ + 0.4921875, + 0.859375 + ], + [ + 0.5, + 0.859375 + ], + [ + 0.5078125, + 0.859375 + ], + [ + 0.515625, + 0.859375 + ], + [ + 0.5234375, + 0.859375 + ], + [ + 0.53125, + 0.859375 + ], + [ + 0.5390625, + 0.859375 + ], + [ + 0.546875, + 0.859375 + ], + [ + 0.5546875, + 0.859375 + ], + [ + 0.5625, + 0.859375 + ], + [ + 0.5703125, + 0.859375 + ], + [ + 0.578125, + 0.859375 + ], + [ + 0.5859375, + 0.859375 + ], + [ + 0.59375, + 0.859375 + ], + [ + 0.6015625, + 0.859375 + ], + [ + 0.609375, + 0.859375 + ], + [ + 0.6171875, + 0.859375 + ], + [ + 0.625, + 0.859375 + ], + [ + 0.6328125, + 0.859375 + ], + [ + 0.640625, + 0.859375 + ], + [ + 0.6484375, + 0.859375 + ], + [ + 0.65625, + 0.859375 + ], + [ + 0.6640625, + 0.859375 + ], + [ + 0.671875, + 0.859375 + ], + [ + 0.6796875, + 0.859375 + ], + [ + 0.6875, + 0.859375 + ], + [ + 0.6953125, + 0.859375 + ], + [ + 0.703125, + 0.859375 + ], + [ + 0.7109375, + 0.859375 + ], + [ + 0.71875, + 0.859375 + ], + [ + 0.7265625, + 0.859375 + ], + [ + 0.734375, + 0.859375 + ], + [ + 0.7421875, + 0.859375 + ], + [ + 0.75, + 0.859375 + ], + [ + 0.7578125, + 0.859375 + ], + [ + 0.765625, + 0.859375 + ], + [ + 0.7734375, + 0.859375 + ], + [ + 0.78125, + 0.859375 + ], + [ + 0.7890625, + 0.859375 + ], + [ + 0.796875, + 0.8515625 + ], + [ + 0.796875, + 0.84375 + ], + [ + 0.8046875, + 0.8359375 + ], + [ + 0.8125, + 0.828125 + ], + [ + 0.8125, + 0.8203125 + ], + [ + 0.8203125, + 0.8125 + ], + [ + 0.8203125, + 0.8046875 + ], + [ + 0.828125, + 0.796875 + ], + [ + 0.8359375, + 0.7890625 + ], + [ + 0.8359375, + 0.78125 + ], + [ + 0.84375, + 0.7734375 + ], + [ + 0.84375, + 0.765625 + ], + [ + 0.8515625, + 0.7578125 + ], + [ + 0.859375, + 0.75 + ], + [ + 0.859375, + 0.7421875 + ], + [ + 0.8671875, + 0.734375 + ], + [ + 0.8671875, + 0.7265625 + ], + [ + 0.875, + 0.71875 + ], + [ + 0.8828125, + 0.7109375 + ], + [ + 0.8828125, + 0.703125 + ], + [ + 0.890625, + 0.6953125 + ], + [ + 0.890625, + 0.6875 + ], + [ + 0.8984375, + 0.6796875 + ], + [ + 0.90625, + 0.671875 + ], + [ + 0.90625, + 0.6640625 + ], + [ + 0.9140625, + 0.65625 + ], + [ + 0.9140625, + 0.6484375 + ], + [ + 0.921875, + 0.640625 + ], + [ + 0.9296875, + 0.6328125 + ], + [ + 0.9296875, + 0.625 + ], + [ + 0.9375, + 0.6171875 + ], + [ + 0.9375, + 0.609375 + ], + [ + 0.9453125, + 0.6015625 + ], + [ + 0.953125, + 0.59375 + ], + [ + 0.953125, + 0.5859375 + ], + [ + 0.9609375, + 0.578125 + ], + [ + 0.9609375, + 0.5703125 + ], + [ + 0.96875, + 0.5625 + ], + [ + 0.9765625, + 0.5546875 + ], + [ + 0.9765625, + 0.546875 + ], + [ + 0.984375, + 0.5390625 + ], + [ + 0.984375, + 0.53125 + ], + [ + 0.984375, + 0.5234375 + ], + [ + 0.9765625, + 0.515625 + ], + [ + 0.9765625, + 0.5078125 + ], + [ + 0.96875, + 0.5 + ], + [ + 0.9609375, + 0.4921875 + ], + [ + 0.9609375, + 0.484375 + ], + [ + 0.953125, + 0.4765625 + ], + [ + 0.953125, + 0.46875 + ], + [ + 0.9453125, + 0.4609375 + ], + [ + 0.9375, + 0.453125 + ], + [ + 0.9375, + 0.4453125 + ], + [ + 0.9296875, + 0.4375 + ], + [ + 0.9375, + 0.4296875 + ], + [ + 0.9375, + 0.421875 + ], + [ + 0.9453125, + 0.4140625 + ], + [ + 0.9453125, + 0.40625 + ], + [ + 0.953125, + 0.3984375 + ], + [ + 0.953125, + 0.390625 + ], + [ + 0.9609375, + 0.3828125 + ], + [ + 0.96875, + 0.375 + ], + [ + 0.96875, + 0.3671875 + ], + [ + 0.9765625, + 0.359375 + ], + [ + 0.9765625, + 0.3515625 + ], + [ + 0.984375, + 0.34375 + ], + [ + 0.984375, + 0.3359375 + ], + [ + 0.984375, + 0.328125 + ], + [ + 0.9765625, + 0.3203125 + ], + [ + 0.9765625, + 0.3125 + ], + [ + 0.96875, + 0.3046875 + ], + [ + 0.96875, + 0.296875 + ], + [ + 0.9609375, + 0.2890625 + ], + [ + 0.953125, + 0.28125 + ], + [ + 0.953125, + 0.2734375 + ], + [ + 0.9453125, + 0.265625 + ], + [ + 0.9453125, + 0.2578125 + ], + [ + 0.9375, + 0.25 + ], + [ + 0.9375, + 0.2421875 + ], + [ + 0.9296875, + 0.234375 + ], + [ + 0.921875, + 0.2265625 + ], + [ + 0.921875, + 0.21875 + ], + [ + 0.9140625, + 0.2109375 + ], + [ + 0.9140625, + 0.203125 + ], + [ + 0.90625, + 0.1953125 + ], + [ + 0.8984375, + 0.1875 + ], + [ + 0.8984375, + 0.1796875 + ], + [ + 0.890625, + 0.171875 + ], + [ + 0.890625, + 0.1640625 + ], + [ + 0.8828125, + 0.15625 + ], + [ + 0.8828125, + 0.1484375 + ], + [ + 0.875, + 0.140625 + ], + [ + 0.8671875, + 0.1328125 + ], + [ + 0.8671875, + 0.125 + ], + [ + 0.859375, + 0.1171875 + ], + [ + 0.859375, + 0.109375 + ], + [ + 0.8515625, + 0.1015625 + ], + [ + 0.84375, + 0.09375 + ], + [ + 0.8515625, + 0.0859375 + ], + [ + 0.859375, + 0.078125 + ], + [ + 0.859375, + 0.0703125 + ], + [ + 0.8671875, + 0.0625 + ], + [ + 0.875, + 0.0546875 + ], + [ + 0.875, + 0.046875 + ], + [ + 0.875, + 0.0390625 + ], + [ + 0.8671875, + 0.03125 + ], + [ + 0.859375, + 0.0234375 + ], + [ + 0.8515625, + 0.015625 + ], + [ + 0.84375, + 0.0078125 + ], + [ + 0.84375, + 0.0 + ], + [ + 0.8359375, + 0.0 + ], + [ + 0.828125, + 0.0 + ], + [ + 0.8203125, + 0.0 + ], + [ + 0.8125, + 0.0 + ], + [ + 0.8046875, + 0.0 + ], + [ + 0.796875, + 0.0 + ], + [ + 0.7890625, + 0.0 + ], + [ + 0.78125, + 0.0 + ], + [ + 0.7734375, + 0.0 + ], + [ + 0.765625, + 0.0 + ], + [ + 0.7578125, + 0.0 + ], + [ + 0.75, + 0.0 + ], + [ + 0.7421875, + 0.0 + ], + [ + 0.734375, + 0.0 + ], + [ + 0.7265625, + 0.0 + ], + [ + 0.71875, + 0.0 + ], + [ + 0.7109375, + 0.0 + ], + [ + 0.703125, + 0.0 + ], + [ + 0.6953125, + 0.0 + ], + [ + 0.6875, + 0.0 + ], + [ + 0.6796875, + 0.0 + ], + [ + 0.671875, + 0.0 + ], + [ + 0.6640625, + 0.0 + ], + [ + 0.65625, + 0.0 + ], + [ + 0.6484375, + 0.0 + ], + [ + 0.640625, + 0.0 + ], + [ + 0.6328125, + 0.0 + ], + [ + 0.625, + 0.0 + ], + [ + 0.6171875, + 0.0 + ], + [ + 0.609375, + 0.0 + ], + [ + 0.6015625, + 0.0 + ], + [ + 0.59375, + 0.0 + ], + [ + 0.5859375, + 0.0 + ], + [ + 0.578125, + 0.0 + ], + [ + 0.5703125, + 0.0 + ], + [ + 0.5625, + 0.0 + ], + [ + 0.5546875, + 0.0 + ], + [ + 0.546875, + 0.0 + ], + [ + 0.5390625, + 0.0 + ], + [ + 0.53125, + 0.0 + ], + [ + 0.5234375, + 0.0 + ], + [ + 0.515625, + 0.0 + ], + [ + 0.5078125, + 0.0 + ], + [ + 0.5, + 0.0 + ], + [ + 0.4921875, + 0.0 + ], + [ + 0.484375, + 0.0 + ], + [ + 0.4765625, + 0.0 + ], + [ + 0.46875, + 0.0 + ], + [ + 0.4609375, + 0.0 + ], + [ + 0.453125, + 0.0 + ], + [ + 0.4453125, + 0.0 + ], + [ + 0.4375, + 0.0 + ], + [ + 0.4296875, + 0.0 + ], + [ + 0.421875, + 0.0 + ], + [ + 0.4140625, + 0.0 + ] + ] + ], + "18": [ + [ + [ + 0.5078125, + 0.1328125 + ], + [ + 0.5078125, + 0.140625 + ], + [ + 0.5, + 0.1484375 + ], + [ + 0.5, + 0.15625 + ], + [ + 0.4921875, + 0.1640625 + ], + [ + 0.484375, + 0.171875 + ], + [ + 0.484375, + 0.1796875 + ], + [ + 0.4765625, + 0.1875 + ], + [ + 0.4765625, + 0.1953125 + ], + [ + 0.46875, + 0.203125 + ], + [ + 0.4609375, + 0.2109375 + ], + [ + 0.4609375, + 0.21875 + ], + [ + 0.453125, + 0.2265625 + ], + [ + 0.453125, + 0.234375 + ], + [ + 0.4453125, + 0.2421875 + ], + [ + 0.4375, + 0.25 + ], + [ + 0.4375, + 0.2578125 + ], + [ + 0.4296875, + 0.265625 + ], + [ + 0.4296875, + 0.2734375 + ], + [ + 0.421875, + 0.28125 + ], + [ + 0.421875, + 0.2890625 + ], + [ + 0.421875, + 0.296875 + ], + [ + 0.4296875, + 0.3046875 + ], + [ + 0.4296875, + 0.3125 + ], + [ + 0.4375, + 0.3203125 + ], + [ + 0.4375, + 0.328125 + ], + [ + 0.4453125, + 0.3359375 + ], + [ + 0.453125, + 0.34375 + ], + [ + 0.453125, + 0.3515625 + ], + [ + 0.4609375, + 0.359375 + ], + [ + 0.4609375, + 0.3671875 + ], + [ + 0.46875, + 0.375 + ], + [ + 0.46875, + 0.3828125 + ], + [ + 0.4765625, + 0.390625 + ], + [ + 0.484375, + 0.3984375 + ], + [ + 0.484375, + 0.40625 + ], + [ + 0.4921875, + 0.4140625 + ], + [ + 0.4921875, + 0.421875 + ], + [ + 0.5, + 0.4296875 + ], + [ + 0.5, + 0.4375 + ], + [ + 0.5078125, + 0.4453125 + ], + [ + 0.515625, + 0.4453125 + ], + [ + 0.5234375, + 0.4453125 + ], + [ + 0.53125, + 0.4453125 + ], + [ + 0.5390625, + 0.4453125 + ], + [ + 0.546875, + 0.4453125 + ], + [ + 0.5546875, + 0.4453125 + ], + [ + 0.5625, + 0.4453125 + ], + [ + 0.5703125, + 0.4453125 + ], + [ + 0.578125, + 0.4453125 + ], + [ + 0.5859375, + 0.4453125 + ], + [ + 0.59375, + 0.4453125 + ], + [ + 0.6015625, + 0.4453125 + ], + [ + 0.609375, + 0.4453125 + ], + [ + 0.6171875, + 0.4453125 + ], + [ + 0.625, + 0.4453125 + ], + [ + 0.6328125, + 0.4453125 + ], + [ + 0.640625, + 0.4453125 + ], + [ + 0.6484375, + 0.4453125 + ], + [ + 0.65625, + 0.4453125 + ], + [ + 0.6640625, + 0.4453125 + ], + [ + 0.671875, + 0.4453125 + ], + [ + 0.6796875, + 0.4453125 + ], + [ + 0.6875, + 0.4453125 + ], + [ + 0.6953125, + 0.4453125 + ], + [ + 0.703125, + 0.4453125 + ], + [ + 0.7109375, + 0.4375 + ], + [ + 0.7109375, + 0.4296875 + ], + [ + 0.71875, + 0.421875 + ], + [ + 0.7265625, + 0.4140625 + ], + [ + 0.7265625, + 0.40625 + ], + [ + 0.734375, + 0.3984375 + ], + [ + 0.734375, + 0.390625 + ], + [ + 0.7421875, + 0.3828125 + ], + [ + 0.75, + 0.375 + ], + [ + 0.75, + 0.3671875 + ], + [ + 0.7578125, + 0.359375 + ], + [ + 0.765625, + 0.3515625 + ], + [ + 0.765625, + 0.34375 + ], + [ + 0.7734375, + 0.3359375 + ], + [ + 0.7734375, + 0.328125 + ], + [ + 0.78125, + 0.3203125 + ], + [ + 0.7890625, + 0.3125 + ], + [ + 0.7890625, + 0.3046875 + ], + [ + 0.796875, + 0.296875 + ], + [ + 0.796875, + 0.2890625 + ], + [ + 0.796875, + 0.28125 + ], + [ + 0.7890625, + 0.2734375 + ], + [ + 0.7890625, + 0.265625 + ], + [ + 0.78125, + 0.2578125 + ], + [ + 0.7734375, + 0.25 + ], + [ + 0.7734375, + 0.2421875 + ], + [ + 0.765625, + 0.234375 + ], + [ + 0.7578125, + 0.2265625 + ], + [ + 0.7578125, + 0.21875 + ], + [ + 0.75, + 0.2109375 + ], + [ + 0.7421875, + 0.203125 + ], + [ + 0.7421875, + 0.1953125 + ], + [ + 0.734375, + 0.1875 + ], + [ + 0.7265625, + 0.1796875 + ], + [ + 0.7265625, + 0.171875 + ], + [ + 0.71875, + 0.1640625 + ], + [ + 0.7109375, + 0.15625 + ], + [ + 0.7109375, + 0.1484375 + ], + [ + 0.703125, + 0.140625 + ], + [ + 0.703125, + 0.1328125 + ], + [ + 0.6953125, + 0.1328125 + ], + [ + 0.6875, + 0.1328125 + ], + [ + 0.6796875, + 0.1328125 + ], + [ + 0.671875, + 0.1328125 + ], + [ + 0.6640625, + 0.1328125 + ], + [ + 0.65625, + 0.1328125 + ], + [ + 0.6484375, + 0.1328125 + ], + [ + 0.640625, + 0.1328125 + ], + [ + 0.6328125, + 0.1328125 + ], + [ + 0.625, + 0.1328125 + ], + [ + 0.6171875, + 0.1328125 + ], + [ + 0.609375, + 0.1328125 + ], + [ + 0.6015625, + 0.1328125 + ], + [ + 0.59375, + 0.1328125 + ], + [ + 0.5859375, + 0.1328125 + ], + [ + 0.578125, + 0.1328125 + ], + [ + 0.5703125, + 0.1328125 + ], + [ + 0.5625, + 0.1328125 + ], + [ + 0.5546875, + 0.1328125 + ], + [ + 0.546875, + 0.1328125 + ], + [ + 0.5390625, + 0.1328125 + ], + [ + 0.53125, + 0.1328125 + ], + [ + 0.5234375, + 0.1328125 + ], + [ + 0.515625, + 0.1328125 + ] + ], + [ + [ + 0.1171875, + 0.0 + ], + [ + 0.1171875, + 0.0078125 + ], + [ + 0.109375, + 0.015625 + ], + [ + 0.109375, + 0.0234375 + ], + [ + 0.1015625, + 0.03125 + ], + [ + 0.09375, + 0.0390625 + ], + [ + 0.09375, + 0.046875 + ], + [ + 0.0859375, + 0.0546875 + ], + [ + 0.0859375, + 0.0625 + ], + [ + 0.078125, + 0.0703125 + ], + [ + 0.0703125, + 0.078125 + ], + [ + 0.0703125, + 0.0859375 + ], + [ + 0.0625, + 0.09375 + ], + [ + 0.0625, + 0.1015625 + ], + [ + 0.0546875, + 0.109375 + ], + [ + 0.046875, + 0.1171875 + ], + [ + 0.046875, + 0.125 + ], + [ + 0.0390625, + 0.1328125 + ], + [ + 0.0390625, + 0.140625 + ], + [ + 0.03125, + 0.1484375 + ], + [ + 0.03125, + 0.15625 + ], + [ + 0.03125, + 0.1640625 + ], + [ + 0.0390625, + 0.171875 + ], + [ + 0.0390625, + 0.1796875 + ], + [ + 0.046875, + 0.1875 + ], + [ + 0.046875, + 0.1953125 + ], + [ + 0.0546875, + 0.203125 + ], + [ + 0.0625, + 0.2109375 + ], + [ + 0.0625, + 0.21875 + ], + [ + 0.0703125, + 0.2265625 + ], + [ + 0.0703125, + 0.234375 + ], + [ + 0.078125, + 0.2421875 + ], + [ + 0.078125, + 0.25 + ], + [ + 0.0859375, + 0.2578125 + ], + [ + 0.09375, + 0.265625 + ], + [ + 0.09375, + 0.2734375 + ], + [ + 0.1015625, + 0.28125 + ], + [ + 0.1015625, + 0.2890625 + ], + [ + 0.109375, + 0.296875 + ], + [ + 0.109375, + 0.3046875 + ], + [ + 0.1171875, + 0.3125 + ], + [ + 0.125, + 0.3125 + ], + [ + 0.1328125, + 0.3125 + ], + [ + 0.140625, + 0.3125 + ], + [ + 0.1484375, + 0.3125 + ], + [ + 0.15625, + 0.3125 + ], + [ + 0.1640625, + 0.3125 + ], + [ + 0.171875, + 0.3125 + ], + [ + 0.1796875, + 0.3125 + ], + [ + 0.1875, + 0.3125 + ], + [ + 0.1953125, + 0.3125 + ], + [ + 0.203125, + 0.3125 + ], + [ + 0.2109375, + 0.3125 + ], + [ + 0.21875, + 0.3125 + ], + [ + 0.2265625, + 0.3125 + ], + [ + 0.234375, + 0.3125 + ], + [ + 0.2421875, + 0.3125 + ], + [ + 0.25, + 0.3125 + ], + [ + 0.2578125, + 0.3125 + ], + [ + 0.265625, + 0.3125 + ], + [ + 0.2734375, + 0.3125 + ], + [ + 0.28125, + 0.3125 + ], + [ + 0.2890625, + 0.3125 + ], + [ + 0.296875, + 0.3125 + ], + [ + 0.3046875, + 0.3125 + ], + [ + 0.3125, + 0.3125 + ], + [ + 0.3203125, + 0.3046875 + ], + [ + 0.3203125, + 0.296875 + ], + [ + 0.328125, + 0.2890625 + ], + [ + 0.3359375, + 0.28125 + ], + [ + 0.3359375, + 0.2734375 + ], + [ + 0.34375, + 0.265625 + ], + [ + 0.34375, + 0.2578125 + ], + [ + 0.3515625, + 0.25 + ], + [ + 0.359375, + 0.2421875 + ], + [ + 0.359375, + 0.234375 + ], + [ + 0.3671875, + 0.2265625 + ], + [ + 0.375, + 0.21875 + ], + [ + 0.375, + 0.2109375 + ], + [ + 0.3828125, + 0.203125 + ], + [ + 0.3828125, + 0.1953125 + ], + [ + 0.390625, + 0.1875 + ], + [ + 0.3984375, + 0.1796875 + ], + [ + 0.3984375, + 0.171875 + ], + [ + 0.40625, + 0.1640625 + ], + [ + 0.40625, + 0.15625 + ], + [ + 0.40625, + 0.1484375 + ], + [ + 0.3984375, + 0.140625 + ], + [ + 0.3984375, + 0.1328125 + ], + [ + 0.390625, + 0.125 + ], + [ + 0.3828125, + 0.1171875 + ], + [ + 0.3828125, + 0.109375 + ], + [ + 0.375, + 0.1015625 + ], + [ + 0.3671875, + 0.09375 + ], + [ + 0.3671875, + 0.0859375 + ], + [ + 0.359375, + 0.078125 + ], + [ + 0.3515625, + 0.0703125 + ], + [ + 0.3515625, + 0.0625 + ], + [ + 0.34375, + 0.0546875 + ], + [ + 0.3359375, + 0.046875 + ], + [ + 0.3359375, + 0.0390625 + ], + [ + 0.328125, + 0.03125 + ], + [ + 0.3203125, + 0.0234375 + ], + [ + 0.3203125, + 0.015625 + ], + [ + 0.3125, + 0.0078125 + ], + [ + 0.3125, + 0.0 + ], + [ + 0.3046875, + 0.0 + ], + [ + 0.296875, + 0.0 + ], + [ + 0.2890625, + 0.0 + ], + [ + 0.28125, + 0.0 + ], + [ + 0.2734375, + 0.0 + ], + [ + 0.265625, + 0.0 + ], + [ + 0.2578125, + 0.0 + ], + [ + 0.25, + 0.0 + ], + [ + 0.2421875, + 0.0 + ], + [ + 0.234375, + 0.0 + ], + [ + 0.2265625, + 0.0 + ], + [ + 0.21875, + 0.0 + ], + [ + 0.2109375, + 0.0 + ], + [ + 0.203125, + 0.0 + ], + [ + 0.1953125, + 0.0 + ], + [ + 0.1875, + 0.0 + ], + [ + 0.1796875, + 0.0 + ], + [ + 0.171875, + 0.0 + ], + [ + 0.1640625, + 0.0 + ], + [ + 0.15625, + 0.0 + ], + [ + 0.1484375, + 0.0 + ], + [ + 0.140625, + 0.0 + ], + [ + 0.1328125, + 0.0 + ], + [ + 0.125, + 0.0 + ] + ] + ] + } +} \ No newline at end of file diff --git a/data/anomaly/segmentation/train.json b/data/anomaly/segmentation/train.json new file mode 100644 index 00000000000..6b5e6dedcc4 --- /dev/null +++ b/data/anomaly/segmentation/train.json @@ -0,0 +1,47 @@ +{ + "image_path": { + "0": "train/good/000.png", + "1": "train/good/001.png", + "2": "train/good/002.png", + "3": "train/good/003.png", + "4": "train/good/004.png", + "5": "train/good/005.png", + "6": "train/good/006.png", + "7": "train/good/007.png", + "8": "train/good/008.png", + "9": "train/good/009.png", + "10": "train/good/010.png", + "11": "train/good/011.png", + "12": "train/good/012.png", + "13": "train/good/013.png", + "14": "train/good/014.png", + "15": "train/good/015.png", + "16": "train/good/016.png", + "17": "train/good/017.png", + "18": "train/good/018.png", + "19": "train/good/019.png" + }, + "label": { + "0": "good", + "1": "good", + "2": "good", + "3": "good", + "4": "good", + "5": "good", + "6": "good", + "7": "good", + "8": "good", + "9": "good", + "10": "good", + "11": "good", + "12": "good", + "13": "good", + "14": "good", + "15": "good", + "16": "good", + "17": "good", + "18": "good", + "19": "good" + }, + "masks": {} +} diff --git a/data/anomaly/segmentation/val.json b/data/anomaly/segmentation/val.json new file mode 100644 index 00000000000..f5d025c41e3 --- /dev/null +++ b/data/anomaly/segmentation/val.json @@ -0,0 +1,12778 @@ +{ + "image_path": { + "1": "test/good/000.png", + "2": "test/good/001.png", + "3": "test/good/002.png", + "4": "test/good/003.png", + "5": "test/star/000.png", + "6": "test/star/001.png", + "7": "test/star/002.png", + "8": "test/star/003.png", + "9": "test/hexagon/000.png", + "10": "test/hexagon/001.png", + "11": "test/hexagon/002.png", + "12": "test/hexagon/003.png" + }, + "label": { + "1": "good", + "2": "good", + "3": "good", + "4": "good", + "5": "star", + "6": "star", + "7": "star", + "8": "star", + "9": "hexagon", + "10": "hexagon", + "11": "hexagon", + "12": "hexagon" + }, + "masks": { + "5": [ + [ + [ + 0.2109375, + 0.109375 + ], + [ + 0.2109375, + 0.1171875 + ], + [ + 0.2109375, + 0.125 + ], + [ + 0.2109375, + 0.1328125 + ], + [ + 0.2109375, + 0.140625 + ], + [ + 0.21875, + 0.1484375 + ], + [ + 0.21875, + 0.15625 + ], + [ + 0.21875, + 0.1640625 + ], + [ + 0.21875, + 0.171875 + ], + [ + 0.21875, + 0.1796875 + ], + [ + 0.2265625, + 0.1875 + ], + [ + 0.2265625, + 0.1953125 + ], + [ + 0.2265625, + 0.203125 + ], + [ + 0.2265625, + 0.2109375 + ], + [ + 0.2265625, + 0.21875 + ], + [ + 0.234375, + 0.2265625 + ], + [ + 0.234375, + 0.234375 + ], + [ + 0.234375, + 0.2421875 + ], + [ + 0.2265625, + 0.25 + ], + [ + 0.21875, + 0.2421875 + ], + [ + 0.2109375, + 0.2421875 + ], + [ + 0.203125, + 0.234375 + ], + [ + 0.1953125, + 0.234375 + ], + [ + 0.1875, + 0.2265625 + ], + [ + 0.1875, + 0.234375 + ], + [ + 0.1875, + 0.2421875 + ], + [ + 0.1875, + 0.25 + ], + [ + 0.1875, + 0.2578125 + ], + [ + 0.1953125, + 0.265625 + ], + [ + 0.1953125, + 0.2734375 + ], + [ + 0.1953125, + 0.28125 + ], + [ + 0.1953125, + 0.2890625 + ], + [ + 0.1953125, + 0.296875 + ], + [ + 0.203125, + 0.3046875 + ], + [ + 0.203125, + 0.3125 + ], + [ + 0.203125, + 0.3203125 + ], + [ + 0.203125, + 0.328125 + ], + [ + 0.203125, + 0.3359375 + ], + [ + 0.2109375, + 0.34375 + ], + [ + 0.2109375, + 0.3515625 + ], + [ + 0.2109375, + 0.359375 + ], + [ + 0.2109375, + 0.3671875 + ], + [ + 0.2109375, + 0.375 + ], + [ + 0.21875, + 0.3828125 + ], + [ + 0.21875, + 0.390625 + ], + [ + 0.21875, + 0.3984375 + ], + [ + 0.21875, + 0.40625 + ], + [ + 0.21875, + 0.4140625 + ], + [ + 0.2265625, + 0.421875 + ], + [ + 0.2265625, + 0.4296875 + ], + [ + 0.2265625, + 0.4375 + ], + [ + 0.2265625, + 0.4453125 + ], + [ + 0.2265625, + 0.453125 + ], + [ + 0.2265625, + 0.4609375 + ], + [ + 0.21875, + 0.46875 + ], + [ + 0.2109375, + 0.4765625 + ], + [ + 0.203125, + 0.484375 + ], + [ + 0.1953125, + 0.4921875 + ], + [ + 0.1875, + 0.5 + ], + [ + 0.1796875, + 0.5078125 + ], + [ + 0.171875, + 0.515625 + ], + [ + 0.1640625, + 0.5234375 + ], + [ + 0.15625, + 0.53125 + ], + [ + 0.1484375, + 0.53125 + ], + [ + 0.140625, + 0.5390625 + ], + [ + 0.1328125, + 0.546875 + ], + [ + 0.125, + 0.5546875 + ], + [ + 0.1171875, + 0.5625 + ], + [ + 0.109375, + 0.5703125 + ], + [ + 0.1015625, + 0.578125 + ], + [ + 0.09375, + 0.5859375 + ], + [ + 0.0859375, + 0.59375 + ], + [ + 0.078125, + 0.6015625 + ], + [ + 0.0703125, + 0.609375 + ], + [ + 0.0625, + 0.6171875 + ], + [ + 0.0546875, + 0.625 + ], + [ + 0.046875, + 0.6328125 + ], + [ + 0.0390625, + 0.640625 + ], + [ + 0.046875, + 0.640625 + ], + [ + 0.0546875, + 0.640625 + ], + [ + 0.0625, + 0.640625 + ], + [ + 0.0703125, + 0.6484375 + ], + [ + 0.0625, + 0.65625 + ], + [ + 0.0546875, + 0.6640625 + ], + [ + 0.046875, + 0.671875 + ], + [ + 0.0390625, + 0.6796875 + ], + [ + 0.03125, + 0.6875 + ], + [ + 0.0390625, + 0.6875 + ], + [ + 0.046875, + 0.6875 + ], + [ + 0.0546875, + 0.6875 + ], + [ + 0.0625, + 0.6875 + ], + [ + 0.0703125, + 0.6875 + ], + [ + 0.078125, + 0.6875 + ], + [ + 0.0859375, + 0.6953125 + ], + [ + 0.09375, + 0.6953125 + ], + [ + 0.1015625, + 0.6953125 + ], + [ + 0.109375, + 0.6953125 + ], + [ + 0.1171875, + 0.6953125 + ], + [ + 0.125, + 0.6953125 + ], + [ + 0.1328125, + 0.6953125 + ], + [ + 0.140625, + 0.703125 + ], + [ + 0.1484375, + 0.703125 + ], + [ + 0.15625, + 0.703125 + ], + [ + 0.1640625, + 0.703125 + ], + [ + 0.171875, + 0.703125 + ], + [ + 0.1796875, + 0.703125 + ], + [ + 0.1875, + 0.703125 + ], + [ + 0.1953125, + 0.703125 + ], + [ + 0.203125, + 0.7109375 + ], + [ + 0.2109375, + 0.7109375 + ], + [ + 0.21875, + 0.7109375 + ], + [ + 0.2265625, + 0.7109375 + ], + [ + 0.234375, + 0.7109375 + ], + [ + 0.2421875, + 0.7109375 + ], + [ + 0.25, + 0.7109375 + ], + [ + 0.2578125, + 0.71875 + ], + [ + 0.265625, + 0.71875 + ], + [ + 0.2734375, + 0.7265625 + ], + [ + 0.28125, + 0.7265625 + ], + [ + 0.2890625, + 0.7265625 + ], + [ + 0.296875, + 0.7265625 + ], + [ + 0.3046875, + 0.7265625 + ], + [ + 0.3125, + 0.7265625 + ], + [ + 0.3203125, + 0.734375 + ], + [ + 0.3203125, + 0.7421875 + ], + [ + 0.328125, + 0.75 + ], + [ + 0.328125, + 0.7578125 + ], + [ + 0.3359375, + 0.765625 + ], + [ + 0.3359375, + 0.7734375 + ], + [ + 0.34375, + 0.78125 + ], + [ + 0.34375, + 0.7890625 + ], + [ + 0.3515625, + 0.796875 + ], + [ + 0.3515625, + 0.8046875 + ], + [ + 0.359375, + 0.8125 + ], + [ + 0.359375, + 0.8203125 + ], + [ + 0.359375, + 0.828125 + ], + [ + 0.3671875, + 0.8359375 + ], + [ + 0.3671875, + 0.84375 + ], + [ + 0.375, + 0.8515625 + ], + [ + 0.375, + 0.859375 + ], + [ + 0.3828125, + 0.8671875 + ], + [ + 0.3828125, + 0.875 + ], + [ + 0.390625, + 0.8828125 + ], + [ + 0.390625, + 0.890625 + ], + [ + 0.3984375, + 0.8984375 + ], + [ + 0.3984375, + 0.90625 + ], + [ + 0.3984375, + 0.9140625 + ], + [ + 0.40625, + 0.921875 + ], + [ + 0.40625, + 0.9296875 + ], + [ + 0.4140625, + 0.9375 + ], + [ + 0.4140625, + 0.9453125 + ], + [ + 0.421875, + 0.953125 + ], + [ + 0.421875, + 0.9609375 + ], + [ + 0.4296875, + 0.96875 + ], + [ + 0.4296875, + 0.9765625 + ], + [ + 0.4296875, + 0.96875 + ], + [ + 0.4375, + 0.9609375 + ], + [ + 0.4375, + 0.953125 + ], + [ + 0.4453125, + 0.9453125 + ], + [ + 0.4453125, + 0.9375 + ], + [ + 0.453125, + 0.9296875 + ], + [ + 0.453125, + 0.921875 + ], + [ + 0.4609375, + 0.9140625 + ], + [ + 0.46875, + 0.921875 + ], + [ + 0.4765625, + 0.9296875 + ], + [ + 0.4765625, + 0.9375 + ], + [ + 0.484375, + 0.9453125 + ], + [ + 0.484375, + 0.953125 + ], + [ + 0.4921875, + 0.9609375 + ], + [ + 0.4921875, + 0.96875 + ], + [ + 0.4921875, + 0.9609375 + ], + [ + 0.5, + 0.953125 + ], + [ + 0.5, + 0.9453125 + ], + [ + 0.5078125, + 0.9375 + ], + [ + 0.5078125, + 0.9296875 + ], + [ + 0.515625, + 0.921875 + ], + [ + 0.515625, + 0.9140625 + ], + [ + 0.5234375, + 0.90625 + ], + [ + 0.5234375, + 0.8984375 + ], + [ + 0.53125, + 0.890625 + ], + [ + 0.53125, + 0.8828125 + ], + [ + 0.5390625, + 0.875 + ], + [ + 0.5390625, + 0.8671875 + ], + [ + 0.546875, + 0.859375 + ], + [ + 0.5546875, + 0.8515625 + ], + [ + 0.5625, + 0.859375 + ], + [ + 0.5625, + 0.8671875 + ], + [ + 0.5703125, + 0.875 + ], + [ + 0.5703125, + 0.8828125 + ], + [ + 0.578125, + 0.890625 + ], + [ + 0.578125, + 0.8984375 + ], + [ + 0.5859375, + 0.90625 + ], + [ + 0.5859375, + 0.9140625 + ], + [ + 0.59375, + 0.921875 + ], + [ + 0.59375, + 0.9296875 + ], + [ + 0.6015625, + 0.9375 + ], + [ + 0.6015625, + 0.9453125 + ], + [ + 0.609375, + 0.953125 + ], + [ + 0.609375, + 0.9609375 + ], + [ + 0.6171875, + 0.96875 + ], + [ + 0.6171875, + 0.9765625 + ], + [ + 0.6171875, + 0.96875 + ], + [ + 0.625, + 0.9609375 + ], + [ + 0.625, + 0.953125 + ], + [ + 0.6328125, + 0.9453125 + ], + [ + 0.6328125, + 0.9375 + ], + [ + 0.640625, + 0.9296875 + ], + [ + 0.640625, + 0.921875 + ], + [ + 0.6484375, + 0.9140625 + ], + [ + 0.6484375, + 0.90625 + ], + [ + 0.65625, + 0.8984375 + ], + [ + 0.65625, + 0.890625 + ], + [ + 0.6640625, + 0.8828125 + ], + [ + 0.6640625, + 0.875 + ], + [ + 0.671875, + 0.8671875 + ], + [ + 0.671875, + 0.859375 + ], + [ + 0.6796875, + 0.8515625 + ], + [ + 0.6796875, + 0.84375 + ], + [ + 0.6875, + 0.8359375 + ], + [ + 0.6875, + 0.828125 + ], + [ + 0.6953125, + 0.8203125 + ], + [ + 0.6953125, + 0.8125 + ], + [ + 0.703125, + 0.8046875 + ], + [ + 0.703125, + 0.796875 + ], + [ + 0.7109375, + 0.7890625 + ], + [ + 0.7109375, + 0.78125 + ], + [ + 0.71875, + 0.7734375 + ], + [ + 0.71875, + 0.765625 + ], + [ + 0.7265625, + 0.7578125 + ], + [ + 0.734375, + 0.7578125 + ], + [ + 0.7421875, + 0.7578125 + ], + [ + 0.75, + 0.7578125 + ], + [ + 0.7578125, + 0.7578125 + ], + [ + 0.765625, + 0.7578125 + ], + [ + 0.7734375, + 0.7578125 + ], + [ + 0.78125, + 0.75 + ], + [ + 0.7890625, + 0.75 + ], + [ + 0.796875, + 0.75 + ], + [ + 0.8046875, + 0.75 + ], + [ + 0.8125, + 0.75 + ], + [ + 0.8203125, + 0.75 + ], + [ + 0.828125, + 0.7421875 + ], + [ + 0.8359375, + 0.7421875 + ], + [ + 0.84375, + 0.7421875 + ], + [ + 0.8515625, + 0.7421875 + ], + [ + 0.859375, + 0.7421875 + ], + [ + 0.8671875, + 0.7421875 + ], + [ + 0.875, + 0.734375 + ], + [ + 0.8828125, + 0.734375 + ], + [ + 0.890625, + 0.734375 + ], + [ + 0.8984375, + 0.734375 + ], + [ + 0.90625, + 0.734375 + ], + [ + 0.9140625, + 0.734375 + ], + [ + 0.921875, + 0.7265625 + ], + [ + 0.9296875, + 0.7265625 + ], + [ + 0.9375, + 0.7265625 + ], + [ + 0.9453125, + 0.7265625 + ], + [ + 0.953125, + 0.7265625 + ], + [ + 0.9609375, + 0.7265625 + ], + [ + 0.953125, + 0.71875 + ], + [ + 0.9453125, + 0.7109375 + ], + [ + 0.9375, + 0.703125 + ], + [ + 0.9296875, + 0.6953125 + ], + [ + 0.921875, + 0.6875 + ], + [ + 0.9140625, + 0.6796875 + ], + [ + 0.90625, + 0.671875 + ], + [ + 0.8984375, + 0.6640625 + ], + [ + 0.890625, + 0.65625 + ], + [ + 0.8984375, + 0.6484375 + ], + [ + 0.90625, + 0.640625 + ], + [ + 0.9140625, + 0.640625 + ], + [ + 0.921875, + 0.640625 + ], + [ + 0.9296875, + 0.640625 + ], + [ + 0.9375, + 0.640625 + ], + [ + 0.9453125, + 0.640625 + ], + [ + 0.9375, + 0.6328125 + ], + [ + 0.9296875, + 0.625 + ], + [ + 0.921875, + 0.6171875 + ], + [ + 0.9140625, + 0.609375 + ], + [ + 0.90625, + 0.6015625 + ], + [ + 0.8984375, + 0.59375 + ], + [ + 0.890625, + 0.5859375 + ], + [ + 0.8828125, + 0.578125 + ], + [ + 0.875, + 0.5703125 + ], + [ + 0.8671875, + 0.5625 + ], + [ + 0.859375, + 0.5546875 + ], + [ + 0.8515625, + 0.546875 + ], + [ + 0.84375, + 0.5390625 + ], + [ + 0.8359375, + 0.53125 + ], + [ + 0.828125, + 0.53125 + ], + [ + 0.8203125, + 0.5234375 + ], + [ + 0.8125, + 0.515625 + ], + [ + 0.8046875, + 0.5078125 + ], + [ + 0.796875, + 0.5 + ], + [ + 0.796875, + 0.4921875 + ], + [ + 0.796875, + 0.484375 + ], + [ + 0.8046875, + 0.4765625 + ], + [ + 0.8046875, + 0.46875 + ], + [ + 0.8046875, + 0.4609375 + ], + [ + 0.8046875, + 0.453125 + ], + [ + 0.8046875, + 0.4453125 + ], + [ + 0.8125, + 0.4375 + ], + [ + 0.8125, + 0.4296875 + ], + [ + 0.8125, + 0.421875 + ], + [ + 0.8125, + 0.4140625 + ], + [ + 0.8125, + 0.40625 + ], + [ + 0.8203125, + 0.3984375 + ], + [ + 0.8203125, + 0.390625 + ], + [ + 0.8203125, + 0.3828125 + ], + [ + 0.8203125, + 0.375 + ], + [ + 0.8203125, + 0.3671875 + ], + [ + 0.828125, + 0.359375 + ], + [ + 0.828125, + 0.3515625 + ], + [ + 0.828125, + 0.34375 + ], + [ + 0.828125, + 0.3359375 + ], + [ + 0.828125, + 0.328125 + ], + [ + 0.8203125, + 0.328125 + ], + [ + 0.8125, + 0.3359375 + ], + [ + 0.8046875, + 0.3359375 + ], + [ + 0.796875, + 0.34375 + ], + [ + 0.7890625, + 0.34375 + ], + [ + 0.78125, + 0.3515625 + ], + [ + 0.7734375, + 0.3515625 + ], + [ + 0.765625, + 0.359375 + ], + [ + 0.7578125, + 0.359375 + ], + [ + 0.75, + 0.3671875 + ], + [ + 0.7421875, + 0.3671875 + ], + [ + 0.734375, + 0.375 + ], + [ + 0.7265625, + 0.3671875 + ], + [ + 0.7265625, + 0.359375 + ], + [ + 0.7265625, + 0.3515625 + ], + [ + 0.7265625, + 0.34375 + ], + [ + 0.734375, + 0.3359375 + ], + [ + 0.734375, + 0.328125 + ], + [ + 0.734375, + 0.3203125 + ], + [ + 0.734375, + 0.3125 + ], + [ + 0.734375, + 0.3046875 + ], + [ + 0.7421875, + 0.296875 + ], + [ + 0.7421875, + 0.2890625 + ], + [ + 0.7421875, + 0.28125 + ], + [ + 0.7421875, + 0.2734375 + ], + [ + 0.7421875, + 0.265625 + ], + [ + 0.75, + 0.2578125 + ], + [ + 0.75, + 0.25 + ], + [ + 0.75, + 0.2421875 + ], + [ + 0.75, + 0.234375 + ], + [ + 0.75, + 0.2265625 + ], + [ + 0.7578125, + 0.21875 + ], + [ + 0.7578125, + 0.2109375 + ], + [ + 0.7578125, + 0.203125 + ], + [ + 0.7578125, + 0.1953125 + ], + [ + 0.7578125, + 0.1875 + ], + [ + 0.765625, + 0.1796875 + ], + [ + 0.765625, + 0.171875 + ], + [ + 0.765625, + 0.1640625 + ], + [ + 0.765625, + 0.15625 + ], + [ + 0.765625, + 0.1484375 + ], + [ + 0.7734375, + 0.140625 + ], + [ + 0.7734375, + 0.1328125 + ], + [ + 0.7734375, + 0.125 + ], + [ + 0.7734375, + 0.1171875 + ], + [ + 0.7734375, + 0.109375 + ], + [ + 0.765625, + 0.1171875 + ], + [ + 0.7578125, + 0.1171875 + ], + [ + 0.75, + 0.125 + ], + [ + 0.7421875, + 0.125 + ], + [ + 0.734375, + 0.1328125 + ], + [ + 0.7265625, + 0.1328125 + ], + [ + 0.71875, + 0.140625 + ], + [ + 0.7109375, + 0.140625 + ], + [ + 0.703125, + 0.1484375 + ], + [ + 0.6953125, + 0.1484375 + ], + [ + 0.6875, + 0.15625 + ], + [ + 0.6796875, + 0.15625 + ], + [ + 0.671875, + 0.1640625 + ], + [ + 0.6640625, + 0.1640625 + ], + [ + 0.65625, + 0.171875 + ], + [ + 0.6484375, + 0.171875 + ], + [ + 0.640625, + 0.1796875 + ], + [ + 0.6328125, + 0.1796875 + ], + [ + 0.625, + 0.1875 + ], + [ + 0.6171875, + 0.1875 + ], + [ + 0.609375, + 0.1953125 + ], + [ + 0.6015625, + 0.1953125 + ], + [ + 0.59375, + 0.203125 + ], + [ + 0.5859375, + 0.203125 + ], + [ + 0.578125, + 0.2109375 + ], + [ + 0.5703125, + 0.2109375 + ], + [ + 0.5625, + 0.21875 + ], + [ + 0.5546875, + 0.21875 + ], + [ + 0.546875, + 0.2265625 + ], + [ + 0.5390625, + 0.2265625 + ], + [ + 0.53125, + 0.234375 + ], + [ + 0.5234375, + 0.234375 + ], + [ + 0.515625, + 0.2421875 + ], + [ + 0.5078125, + 0.2421875 + ], + [ + 0.5, + 0.25 + ], + [ + 0.4921875, + 0.25 + ], + [ + 0.484375, + 0.25 + ], + [ + 0.4765625, + 0.2421875 + ], + [ + 0.46875, + 0.2421875 + ], + [ + 0.4609375, + 0.234375 + ], + [ + 0.453125, + 0.234375 + ], + [ + 0.4453125, + 0.2265625 + ], + [ + 0.4375, + 0.2265625 + ], + [ + 0.4296875, + 0.21875 + ], + [ + 0.421875, + 0.21875 + ], + [ + 0.4140625, + 0.2109375 + ], + [ + 0.40625, + 0.2109375 + ], + [ + 0.3984375, + 0.203125 + ], + [ + 0.390625, + 0.203125 + ], + [ + 0.3828125, + 0.1953125 + ], + [ + 0.375, + 0.1953125 + ], + [ + 0.3671875, + 0.1875 + ], + [ + 0.359375, + 0.1875 + ], + [ + 0.3515625, + 0.1796875 + ], + [ + 0.34375, + 0.1796875 + ], + [ + 0.3359375, + 0.171875 + ], + [ + 0.328125, + 0.171875 + ], + [ + 0.3203125, + 0.1640625 + ], + [ + 0.3125, + 0.1640625 + ], + [ + 0.3046875, + 0.15625 + ], + [ + 0.296875, + 0.15625 + ], + [ + 0.2890625, + 0.1484375 + ], + [ + 0.28125, + 0.1484375 + ], + [ + 0.2734375, + 0.140625 + ], + [ + 0.265625, + 0.140625 + ], + [ + 0.2578125, + 0.1328125 + ], + [ + 0.25, + 0.1328125 + ], + [ + 0.2421875, + 0.125 + ], + [ + 0.234375, + 0.125 + ], + [ + 0.2265625, + 0.1171875 + ], + [ + 0.21875, + 0.1171875 + ] + ] + ], + "6": [ + [ + [ + 0.140625, + 0.421875 + ], + [ + 0.140625, + 0.4296875 + ], + [ + 0.140625, + 0.4375 + ], + [ + 0.140625, + 0.4453125 + ], + [ + 0.140625, + 0.453125 + ], + [ + 0.1484375, + 0.4609375 + ], + [ + 0.1484375, + 0.46875 + ], + [ + 0.1484375, + 0.4765625 + ], + [ + 0.1484375, + 0.484375 + ], + [ + 0.1484375, + 0.4921875 + ], + [ + 0.15625, + 0.5 + ], + [ + 0.15625, + 0.5078125 + ], + [ + 0.15625, + 0.515625 + ], + [ + 0.15625, + 0.5234375 + ], + [ + 0.15625, + 0.53125 + ], + [ + 0.15625, + 0.5390625 + ], + [ + 0.1640625, + 0.546875 + ], + [ + 0.1640625, + 0.5546875 + ], + [ + 0.1640625, + 0.5625 + ], + [ + 0.1640625, + 0.5703125 + ], + [ + 0.1640625, + 0.578125 + ], + [ + 0.171875, + 0.5859375 + ], + [ + 0.171875, + 0.59375 + ], + [ + 0.171875, + 0.6015625 + ], + [ + 0.171875, + 0.609375 + ], + [ + 0.171875, + 0.6171875 + ], + [ + 0.171875, + 0.625 + ], + [ + 0.1640625, + 0.6328125 + ], + [ + 0.15625, + 0.640625 + ], + [ + 0.1484375, + 0.6484375 + ], + [ + 0.140625, + 0.65625 + ], + [ + 0.1328125, + 0.6640625 + ], + [ + 0.125, + 0.671875 + ], + [ + 0.1171875, + 0.6796875 + ], + [ + 0.109375, + 0.6875 + ], + [ + 0.1015625, + 0.6953125 + ], + [ + 0.09375, + 0.703125 + ], + [ + 0.0859375, + 0.7109375 + ], + [ + 0.078125, + 0.71875 + ], + [ + 0.0703125, + 0.7265625 + ], + [ + 0.0625, + 0.734375 + ], + [ + 0.0546875, + 0.7421875 + ], + [ + 0.046875, + 0.75 + ], + [ + 0.0390625, + 0.7578125 + ], + [ + 0.03125, + 0.765625 + ], + [ + 0.0390625, + 0.765625 + ], + [ + 0.046875, + 0.765625 + ], + [ + 0.0546875, + 0.765625 + ], + [ + 0.0625, + 0.765625 + ], + [ + 0.0703125, + 0.765625 + ], + [ + 0.078125, + 0.7734375 + ], + [ + 0.0859375, + 0.7734375 + ], + [ + 0.09375, + 0.7734375 + ], + [ + 0.1015625, + 0.7734375 + ], + [ + 0.109375, + 0.7734375 + ], + [ + 0.1171875, + 0.7734375 + ], + [ + 0.125, + 0.7734375 + ], + [ + 0.1328125, + 0.78125 + ], + [ + 0.140625, + 0.78125 + ], + [ + 0.1484375, + 0.78125 + ], + [ + 0.15625, + 0.78125 + ], + [ + 0.1640625, + 0.78125 + ], + [ + 0.171875, + 0.78125 + ], + [ + 0.1796875, + 0.78125 + ], + [ + 0.1875, + 0.7890625 + ], + [ + 0.1953125, + 0.7890625 + ], + [ + 0.203125, + 0.7890625 + ], + [ + 0.2109375, + 0.7890625 + ], + [ + 0.21875, + 0.7890625 + ], + [ + 0.2265625, + 0.7890625 + ], + [ + 0.234375, + 0.7890625 + ], + [ + 0.2421875, + 0.796875 + ], + [ + 0.2421875, + 0.8046875 + ], + [ + 0.2421875, + 0.8125 + ], + [ + 0.25, + 0.8203125 + ], + [ + 0.25, + 0.828125 + ], + [ + 0.2578125, + 0.8359375 + ], + [ + 0.2578125, + 0.84375 + ], + [ + 0.265625, + 0.8515625 + ], + [ + 0.265625, + 0.859375 + ], + [ + 0.2734375, + 0.8671875 + ], + [ + 0.2734375, + 0.875 + ], + [ + 0.28125, + 0.8828125 + ], + [ + 0.28125, + 0.890625 + ], + [ + 0.28125, + 0.8984375 + ], + [ + 0.2890625, + 0.90625 + ], + [ + 0.2890625, + 0.9140625 + ], + [ + 0.296875, + 0.921875 + ], + [ + 0.296875, + 0.9296875 + ], + [ + 0.3046875, + 0.9375 + ], + [ + 0.3046875, + 0.9453125 + ], + [ + 0.3125, + 0.953125 + ], + [ + 0.3125, + 0.9609375 + ], + [ + 0.3203125, + 0.96875 + ], + [ + 0.3203125, + 0.9765625 + ], + [ + 0.3203125, + 0.96875 + ], + [ + 0.328125, + 0.9609375 + ], + [ + 0.328125, + 0.953125 + ], + [ + 0.3359375, + 0.9453125 + ], + [ + 0.3359375, + 0.9375 + ], + [ + 0.34375, + 0.9296875 + ], + [ + 0.34375, + 0.921875 + ], + [ + 0.3515625, + 0.9140625 + ], + [ + 0.3515625, + 0.90625 + ], + [ + 0.359375, + 0.8984375 + ], + [ + 0.359375, + 0.890625 + ], + [ + 0.359375, + 0.8828125 + ], + [ + 0.3671875, + 0.875 + ], + [ + 0.3671875, + 0.8671875 + ], + [ + 0.375, + 0.859375 + ], + [ + 0.375, + 0.8515625 + ], + [ + 0.3828125, + 0.84375 + ], + [ + 0.3828125, + 0.8359375 + ], + [ + 0.390625, + 0.828125 + ], + [ + 0.390625, + 0.8203125 + ], + [ + 0.3984375, + 0.8125 + ], + [ + 0.3984375, + 0.8046875 + ], + [ + 0.3984375, + 0.796875 + ], + [ + 0.40625, + 0.7890625 + ], + [ + 0.4140625, + 0.7890625 + ], + [ + 0.421875, + 0.7890625 + ], + [ + 0.4296875, + 0.7890625 + ], + [ + 0.4375, + 0.7890625 + ], + [ + 0.4453125, + 0.7890625 + ], + [ + 0.453125, + 0.7890625 + ], + [ + 0.4609375, + 0.78125 + ], + [ + 0.46875, + 0.78125 + ], + [ + 0.4765625, + 0.78125 + ], + [ + 0.484375, + 0.78125 + ], + [ + 0.4921875, + 0.78125 + ], + [ + 0.5, + 0.78125 + ], + [ + 0.5078125, + 0.78125 + ], + [ + 0.515625, + 0.7734375 + ], + [ + 0.5234375, + 0.7734375 + ], + [ + 0.53125, + 0.7734375 + ], + [ + 0.5390625, + 0.7734375 + ], + [ + 0.546875, + 0.7734375 + ], + [ + 0.5546875, + 0.78125 + ], + [ + 0.546875, + 0.7890625 + ], + [ + 0.5390625, + 0.796875 + ], + [ + 0.53125, + 0.8046875 + ], + [ + 0.5234375, + 0.8125 + ], + [ + 0.515625, + 0.8203125 + ], + [ + 0.5078125, + 0.828125 + ], + [ + 0.515625, + 0.828125 + ], + [ + 0.5234375, + 0.828125 + ], + [ + 0.53125, + 0.828125 + ], + [ + 0.5390625, + 0.828125 + ], + [ + 0.546875, + 0.828125 + ], + [ + 0.5546875, + 0.8359375 + ], + [ + 0.5625, + 0.8359375 + ], + [ + 0.5703125, + 0.8359375 + ], + [ + 0.578125, + 0.8359375 + ], + [ + 0.5859375, + 0.8359375 + ], + [ + 0.59375, + 0.8359375 + ], + [ + 0.6015625, + 0.8359375 + ], + [ + 0.609375, + 0.84375 + ], + [ + 0.6171875, + 0.84375 + ], + [ + 0.625, + 0.84375 + ], + [ + 0.6328125, + 0.84375 + ], + [ + 0.640625, + 0.84375 + ], + [ + 0.6484375, + 0.84375 + ], + [ + 0.65625, + 0.84375 + ], + [ + 0.6640625, + 0.8515625 + ], + [ + 0.6640625, + 0.859375 + ], + [ + 0.6640625, + 0.8671875 + ], + [ + 0.671875, + 0.875 + ], + [ + 0.671875, + 0.8828125 + ], + [ + 0.6796875, + 0.890625 + ], + [ + 0.6796875, + 0.8984375 + ], + [ + 0.6875, + 0.90625 + ], + [ + 0.6875, + 0.9140625 + ], + [ + 0.6953125, + 0.921875 + ], + [ + 0.6953125, + 0.9296875 + ], + [ + 0.703125, + 0.9375 + ], + [ + 0.703125, + 0.9453125 + ], + [ + 0.7109375, + 0.953125 + ], + [ + 0.7109375, + 0.9609375 + ], + [ + 0.71875, + 0.96875 + ], + [ + 0.71875, + 0.9765625 + ], + [ + 0.71875, + 0.96875 + ], + [ + 0.7265625, + 0.9609375 + ], + [ + 0.7265625, + 0.953125 + ], + [ + 0.734375, + 0.9453125 + ], + [ + 0.734375, + 0.9375 + ], + [ + 0.7421875, + 0.9296875 + ], + [ + 0.7421875, + 0.921875 + ], + [ + 0.75, + 0.9140625 + ], + [ + 0.75, + 0.90625 + ], + [ + 0.7578125, + 0.8984375 + ], + [ + 0.7578125, + 0.890625 + ], + [ + 0.765625, + 0.8828125 + ], + [ + 0.765625, + 0.875 + ], + [ + 0.7734375, + 0.8671875 + ], + [ + 0.7734375, + 0.859375 + ], + [ + 0.7734375, + 0.8515625 + ], + [ + 0.78125, + 0.84375 + ], + [ + 0.7890625, + 0.84375 + ], + [ + 0.796875, + 0.84375 + ], + [ + 0.8046875, + 0.84375 + ], + [ + 0.8125, + 0.84375 + ], + [ + 0.8203125, + 0.84375 + ], + [ + 0.828125, + 0.84375 + ], + [ + 0.8359375, + 0.8359375 + ], + [ + 0.84375, + 0.8359375 + ], + [ + 0.8515625, + 0.8359375 + ], + [ + 0.859375, + 0.8359375 + ], + [ + 0.8671875, + 0.8359375 + ], + [ + 0.875, + 0.8359375 + ], + [ + 0.8828125, + 0.8359375 + ], + [ + 0.890625, + 0.828125 + ], + [ + 0.8984375, + 0.828125 + ], + [ + 0.90625, + 0.828125 + ], + [ + 0.9140625, + 0.828125 + ], + [ + 0.921875, + 0.828125 + ], + [ + 0.9296875, + 0.828125 + ], + [ + 0.921875, + 0.8203125 + ], + [ + 0.9140625, + 0.8125 + ], + [ + 0.90625, + 0.8046875 + ], + [ + 0.8984375, + 0.796875 + ], + [ + 0.890625, + 0.7890625 + ], + [ + 0.8828125, + 0.78125 + ], + [ + 0.875, + 0.7734375 + ], + [ + 0.8671875, + 0.765625 + ], + [ + 0.859375, + 0.7578125 + ], + [ + 0.8515625, + 0.75 + ], + [ + 0.84375, + 0.7421875 + ], + [ + 0.8359375, + 0.734375 + ], + [ + 0.828125, + 0.7265625 + ], + [ + 0.828125, + 0.71875 + ], + [ + 0.828125, + 0.7109375 + ], + [ + 0.828125, + 0.703125 + ], + [ + 0.828125, + 0.6953125 + ], + [ + 0.828125, + 0.6875 + ], + [ + 0.828125, + 0.6796875 + ], + [ + 0.8359375, + 0.671875 + ], + [ + 0.8359375, + 0.6640625 + ], + [ + 0.8359375, + 0.65625 + ], + [ + 0.8359375, + 0.6484375 + ], + [ + 0.8359375, + 0.640625 + ], + [ + 0.8359375, + 0.6328125 + ], + [ + 0.8359375, + 0.625 + ], + [ + 0.84375, + 0.6171875 + ], + [ + 0.84375, + 0.609375 + ], + [ + 0.84375, + 0.6015625 + ], + [ + 0.84375, + 0.59375 + ], + [ + 0.84375, + 0.5859375 + ], + [ + 0.84375, + 0.578125 + ], + [ + 0.8359375, + 0.5859375 + ], + [ + 0.828125, + 0.5859375 + ], + [ + 0.8203125, + 0.59375 + ], + [ + 0.8125, + 0.59375 + ], + [ + 0.8046875, + 0.6015625 + ], + [ + 0.796875, + 0.6015625 + ], + [ + 0.7890625, + 0.609375 + ], + [ + 0.78125, + 0.609375 + ], + [ + 0.7734375, + 0.6171875 + ], + [ + 0.765625, + 0.6171875 + ], + [ + 0.7578125, + 0.625 + ], + [ + 0.75, + 0.625 + ], + [ + 0.7421875, + 0.6328125 + ], + [ + 0.734375, + 0.6328125 + ], + [ + 0.7265625, + 0.640625 + ], + [ + 0.71875, + 0.640625 + ], + [ + 0.7109375, + 0.640625 + ], + [ + 0.703125, + 0.6328125 + ], + [ + 0.6953125, + 0.6328125 + ], + [ + 0.6875, + 0.625 + ], + [ + 0.6796875, + 0.625 + ], + [ + 0.671875, + 0.6171875 + ], + [ + 0.6640625, + 0.6171875 + ], + [ + 0.65625, + 0.609375 + ], + [ + 0.6484375, + 0.609375 + ], + [ + 0.640625, + 0.6015625 + ], + [ + 0.6328125, + 0.6015625 + ], + [ + 0.625, + 0.59375 + ], + [ + 0.6171875, + 0.59375 + ], + [ + 0.609375, + 0.5859375 + ], + [ + 0.6015625, + 0.5859375 + ], + [ + 0.59375, + 0.578125 + ], + [ + 0.59375, + 0.5859375 + ], + [ + 0.59375, + 0.59375 + ], + [ + 0.59375, + 0.6015625 + ], + [ + 0.59375, + 0.609375 + ], + [ + 0.59375, + 0.6171875 + ], + [ + 0.6015625, + 0.625 + ], + [ + 0.6015625, + 0.6328125 + ], + [ + 0.6015625, + 0.640625 + ], + [ + 0.6015625, + 0.6484375 + ], + [ + 0.6015625, + 0.65625 + ], + [ + 0.6015625, + 0.6640625 + ], + [ + 0.6015625, + 0.671875 + ], + [ + 0.609375, + 0.6796875 + ], + [ + 0.609375, + 0.6875 + ], + [ + 0.609375, + 0.6953125 + ], + [ + 0.609375, + 0.703125 + ], + [ + 0.609375, + 0.7109375 + ], + [ + 0.609375, + 0.71875 + ], + [ + 0.609375, + 0.7265625 + ], + [ + 0.6015625, + 0.734375 + ], + [ + 0.59375, + 0.7421875 + ], + [ + 0.5859375, + 0.7421875 + ], + [ + 0.578125, + 0.734375 + ], + [ + 0.5703125, + 0.7265625 + ], + [ + 0.5625, + 0.71875 + ], + [ + 0.5546875, + 0.7109375 + ], + [ + 0.546875, + 0.703125 + ], + [ + 0.5390625, + 0.6953125 + ], + [ + 0.53125, + 0.6875 + ], + [ + 0.5234375, + 0.6796875 + ], + [ + 0.515625, + 0.671875 + ], + [ + 0.5078125, + 0.6640625 + ], + [ + 0.5, + 0.65625 + ], + [ + 0.4921875, + 0.6484375 + ], + [ + 0.484375, + 0.640625 + ], + [ + 0.4765625, + 0.6328125 + ], + [ + 0.46875, + 0.625 + ], + [ + 0.46875, + 0.6171875 + ], + [ + 0.46875, + 0.609375 + ], + [ + 0.46875, + 0.6015625 + ], + [ + 0.46875, + 0.59375 + ], + [ + 0.46875, + 0.5859375 + ], + [ + 0.4765625, + 0.578125 + ], + [ + 0.4765625, + 0.5703125 + ], + [ + 0.4765625, + 0.5625 + ], + [ + 0.4765625, + 0.5546875 + ], + [ + 0.4765625, + 0.546875 + ], + [ + 0.484375, + 0.5390625 + ], + [ + 0.484375, + 0.53125 + ], + [ + 0.484375, + 0.5234375 + ], + [ + 0.484375, + 0.515625 + ], + [ + 0.484375, + 0.5078125 + ], + [ + 0.484375, + 0.5 + ], + [ + 0.4921875, + 0.4921875 + ], + [ + 0.4921875, + 0.484375 + ], + [ + 0.4921875, + 0.4765625 + ], + [ + 0.4921875, + 0.46875 + ], + [ + 0.4921875, + 0.4609375 + ], + [ + 0.5, + 0.453125 + ], + [ + 0.5, + 0.4453125 + ], + [ + 0.5, + 0.4375 + ], + [ + 0.5, + 0.4296875 + ], + [ + 0.5, + 0.421875 + ], + [ + 0.4921875, + 0.4296875 + ], + [ + 0.484375, + 0.4296875 + ], + [ + 0.4765625, + 0.4375 + ], + [ + 0.46875, + 0.4375 + ], + [ + 0.4609375, + 0.4453125 + ], + [ + 0.453125, + 0.4453125 + ], + [ + 0.4453125, + 0.453125 + ], + [ + 0.4375, + 0.453125 + ], + [ + 0.4296875, + 0.4609375 + ], + [ + 0.421875, + 0.4609375 + ], + [ + 0.4140625, + 0.46875 + ], + [ + 0.40625, + 0.4765625 + ], + [ + 0.3984375, + 0.4765625 + ], + [ + 0.390625, + 0.484375 + ], + [ + 0.3828125, + 0.484375 + ], + [ + 0.375, + 0.4921875 + ], + [ + 0.3671875, + 0.4921875 + ], + [ + 0.359375, + 0.5 + ], + [ + 0.3515625, + 0.5 + ], + [ + 0.34375, + 0.5078125 + ], + [ + 0.3359375, + 0.5078125 + ], + [ + 0.328125, + 0.515625 + ], + [ + 0.3203125, + 0.515625 + ], + [ + 0.3125, + 0.515625 + ], + [ + 0.3046875, + 0.5078125 + ], + [ + 0.296875, + 0.5078125 + ], + [ + 0.2890625, + 0.5 + ], + [ + 0.28125, + 0.5 + ], + [ + 0.2734375, + 0.4921875 + ], + [ + 0.265625, + 0.4921875 + ], + [ + 0.2578125, + 0.484375 + ], + [ + 0.25, + 0.484375 + ], + [ + 0.2421875, + 0.4765625 + ], + [ + 0.234375, + 0.4765625 + ], + [ + 0.2265625, + 0.46875 + ], + [ + 0.21875, + 0.4609375 + ], + [ + 0.2109375, + 0.4609375 + ], + [ + 0.203125, + 0.453125 + ], + [ + 0.1953125, + 0.453125 + ], + [ + 0.1875, + 0.4453125 + ], + [ + 0.1796875, + 0.4453125 + ], + [ + 0.171875, + 0.4375 + ], + [ + 0.1640625, + 0.4375 + ], + [ + 0.15625, + 0.4296875 + ], + [ + 0.1484375, + 0.4296875 + ] + ], + [ + [ + 0.5390625, + 0.1015625 + ], + [ + 0.5390625, + 0.109375 + ], + [ + 0.5390625, + 0.1171875 + ], + [ + 0.5390625, + 0.125 + ], + [ + 0.546875, + 0.1328125 + ], + [ + 0.546875, + 0.140625 + ], + [ + 0.546875, + 0.1484375 + ], + [ + 0.546875, + 0.15625 + ], + [ + 0.5546875, + 0.1640625 + ], + [ + 0.5546875, + 0.171875 + ], + [ + 0.5546875, + 0.1796875 + ], + [ + 0.5546875, + 0.1875 + ], + [ + 0.5546875, + 0.1953125 + ], + [ + 0.546875, + 0.203125 + ], + [ + 0.5390625, + 0.2109375 + ], + [ + 0.53125, + 0.21875 + ], + [ + 0.5234375, + 0.2265625 + ], + [ + 0.515625, + 0.234375 + ], + [ + 0.5078125, + 0.2421875 + ], + [ + 0.5, + 0.25 + ], + [ + 0.4921875, + 0.2578125 + ], + [ + 0.484375, + 0.265625 + ], + [ + 0.4921875, + 0.265625 + ], + [ + 0.5, + 0.265625 + ], + [ + 0.5078125, + 0.265625 + ], + [ + 0.515625, + 0.265625 + ], + [ + 0.5234375, + 0.265625 + ], + [ + 0.53125, + 0.265625 + ], + [ + 0.5390625, + 0.2734375 + ], + [ + 0.546875, + 0.2734375 + ], + [ + 0.5546875, + 0.2734375 + ], + [ + 0.5625, + 0.2734375 + ], + [ + 0.5703125, + 0.2734375 + ], + [ + 0.578125, + 0.2734375 + ], + [ + 0.5859375, + 0.2734375 + ], + [ + 0.59375, + 0.28125 + ], + [ + 0.59375, + 0.2890625 + ], + [ + 0.59375, + 0.296875 + ], + [ + 0.6015625, + 0.3046875 + ], + [ + 0.6015625, + 0.3125 + ], + [ + 0.609375, + 0.3203125 + ], + [ + 0.609375, + 0.328125 + ], + [ + 0.609375, + 0.3359375 + ], + [ + 0.6171875, + 0.34375 + ], + [ + 0.6171875, + 0.3515625 + ], + [ + 0.625, + 0.359375 + ], + [ + 0.625, + 0.3671875 + ], + [ + 0.625, + 0.359375 + ], + [ + 0.6328125, + 0.3515625 + ], + [ + 0.6328125, + 0.34375 + ], + [ + 0.640625, + 0.3359375 + ], + [ + 0.640625, + 0.328125 + ], + [ + 0.640625, + 0.3203125 + ], + [ + 0.6484375, + 0.3125 + ], + [ + 0.6484375, + 0.3046875 + ], + [ + 0.65625, + 0.296875 + ], + [ + 0.65625, + 0.2890625 + ], + [ + 0.65625, + 0.28125 + ], + [ + 0.6640625, + 0.2734375 + ], + [ + 0.671875, + 0.2734375 + ], + [ + 0.6796875, + 0.2734375 + ], + [ + 0.6875, + 0.2734375 + ], + [ + 0.6953125, + 0.2734375 + ], + [ + 0.703125, + 0.2734375 + ], + [ + 0.7109375, + 0.2734375 + ], + [ + 0.71875, + 0.265625 + ], + [ + 0.7265625, + 0.265625 + ], + [ + 0.734375, + 0.265625 + ], + [ + 0.7421875, + 0.265625 + ], + [ + 0.75, + 0.265625 + ], + [ + 0.7578125, + 0.265625 + ], + [ + 0.765625, + 0.265625 + ], + [ + 0.7578125, + 0.2578125 + ], + [ + 0.75, + 0.25 + ], + [ + 0.7421875, + 0.2421875 + ], + [ + 0.734375, + 0.234375 + ], + [ + 0.7265625, + 0.2265625 + ], + [ + 0.71875, + 0.21875 + ], + [ + 0.7109375, + 0.2109375 + ], + [ + 0.703125, + 0.203125 + ], + [ + 0.6953125, + 0.1953125 + ], + [ + 0.6953125, + 0.1875 + ], + [ + 0.6953125, + 0.1796875 + ], + [ + 0.6953125, + 0.171875 + ], + [ + 0.6953125, + 0.1640625 + ], + [ + 0.703125, + 0.15625 + ], + [ + 0.703125, + 0.1484375 + ], + [ + 0.703125, + 0.140625 + ], + [ + 0.703125, + 0.1328125 + ], + [ + 0.7109375, + 0.125 + ], + [ + 0.7109375, + 0.1171875 + ], + [ + 0.7109375, + 0.109375 + ], + [ + 0.7109375, + 0.1015625 + ], + [ + 0.703125, + 0.1015625 + ], + [ + 0.6953125, + 0.109375 + ], + [ + 0.6875, + 0.109375 + ], + [ + 0.6796875, + 0.1171875 + ], + [ + 0.671875, + 0.1171875 + ], + [ + 0.6640625, + 0.125 + ], + [ + 0.65625, + 0.125 + ], + [ + 0.6484375, + 0.1328125 + ], + [ + 0.640625, + 0.1328125 + ], + [ + 0.6328125, + 0.140625 + ], + [ + 0.625, + 0.140625 + ], + [ + 0.6171875, + 0.140625 + ], + [ + 0.609375, + 0.1328125 + ], + [ + 0.6015625, + 0.1328125 + ], + [ + 0.59375, + 0.125 + ], + [ + 0.5859375, + 0.125 + ], + [ + 0.578125, + 0.1171875 + ], + [ + 0.5703125, + 0.1171875 + ], + [ + 0.5625, + 0.109375 + ], + [ + 0.5546875, + 0.109375 + ], + [ + 0.546875, + 0.1015625 + ] + ] + ], + "7": [ + [ + [ + 0.1484375, + 0.140625 + ], + [ + 0.1484375, + 0.1484375 + ], + [ + 0.1484375, + 0.15625 + ], + [ + 0.1484375, + 0.1640625 + ], + [ + 0.1484375, + 0.171875 + ], + [ + 0.15625, + 0.1796875 + ], + [ + 0.15625, + 0.1875 + ], + [ + 0.15625, + 0.1953125 + ], + [ + 0.15625, + 0.203125 + ], + [ + 0.15625, + 0.2109375 + ], + [ + 0.1640625, + 0.21875 + ], + [ + 0.1640625, + 0.2265625 + ], + [ + 0.1640625, + 0.234375 + ], + [ + 0.1640625, + 0.2421875 + ], + [ + 0.1640625, + 0.25 + ], + [ + 0.1640625, + 0.2578125 + ], + [ + 0.171875, + 0.265625 + ], + [ + 0.171875, + 0.2734375 + ], + [ + 0.171875, + 0.28125 + ], + [ + 0.171875, + 0.2890625 + ], + [ + 0.171875, + 0.296875 + ], + [ + 0.1796875, + 0.3046875 + ], + [ + 0.1796875, + 0.3125 + ], + [ + 0.1796875, + 0.3203125 + ], + [ + 0.1796875, + 0.328125 + ], + [ + 0.1796875, + 0.3359375 + ], + [ + 0.1796875, + 0.34375 + ], + [ + 0.171875, + 0.3515625 + ], + [ + 0.1640625, + 0.359375 + ], + [ + 0.15625, + 0.3671875 + ], + [ + 0.1484375, + 0.375 + ], + [ + 0.140625, + 0.3828125 + ], + [ + 0.1328125, + 0.390625 + ], + [ + 0.125, + 0.3984375 + ], + [ + 0.1171875, + 0.40625 + ], + [ + 0.109375, + 0.4140625 + ], + [ + 0.1015625, + 0.4140625 + ], + [ + 0.09375, + 0.421875 + ], + [ + 0.0859375, + 0.4296875 + ], + [ + 0.078125, + 0.4375 + ], + [ + 0.0703125, + 0.4453125 + ], + [ + 0.0625, + 0.453125 + ], + [ + 0.0546875, + 0.4609375 + ], + [ + 0.046875, + 0.46875 + ], + [ + 0.0390625, + 0.4765625 + ], + [ + 0.03125, + 0.484375 + ], + [ + 0.0390625, + 0.484375 + ], + [ + 0.046875, + 0.484375 + ], + [ + 0.0546875, + 0.484375 + ], + [ + 0.0625, + 0.484375 + ], + [ + 0.0703125, + 0.484375 + ], + [ + 0.078125, + 0.4921875 + ], + [ + 0.0859375, + 0.4921875 + ], + [ + 0.09375, + 0.4921875 + ], + [ + 0.1015625, + 0.4921875 + ], + [ + 0.109375, + 0.4921875 + ], + [ + 0.1171875, + 0.4921875 + ], + [ + 0.125, + 0.4921875 + ], + [ + 0.1328125, + 0.5 + ], + [ + 0.140625, + 0.5 + ], + [ + 0.1484375, + 0.5 + ], + [ + 0.15625, + 0.5 + ], + [ + 0.1640625, + 0.5 + ], + [ + 0.171875, + 0.5 + ], + [ + 0.1796875, + 0.5 + ], + [ + 0.1875, + 0.5078125 + ], + [ + 0.1953125, + 0.5078125 + ], + [ + 0.203125, + 0.5078125 + ], + [ + 0.2109375, + 0.5078125 + ], + [ + 0.21875, + 0.5078125 + ], + [ + 0.2265625, + 0.5078125 + ], + [ + 0.234375, + 0.5078125 + ], + [ + 0.2421875, + 0.515625 + ], + [ + 0.2421875, + 0.5234375 + ], + [ + 0.2421875, + 0.53125 + ], + [ + 0.25, + 0.5390625 + ], + [ + 0.25, + 0.546875 + ], + [ + 0.2578125, + 0.5546875 + ], + [ + 0.2578125, + 0.5625 + ], + [ + 0.265625, + 0.5703125 + ], + [ + 0.265625, + 0.578125 + ], + [ + 0.2734375, + 0.5859375 + ], + [ + 0.2734375, + 0.59375 + ], + [ + 0.28125, + 0.6015625 + ], + [ + 0.28125, + 0.609375 + ], + [ + 0.2890625, + 0.6171875 + ], + [ + 0.2890625, + 0.625 + ], + [ + 0.296875, + 0.6328125 + ], + [ + 0.296875, + 0.640625 + ], + [ + 0.3046875, + 0.6484375 + ], + [ + 0.3046875, + 0.65625 + ], + [ + 0.3125, + 0.6640625 + ], + [ + 0.3125, + 0.671875 + ], + [ + 0.3203125, + 0.6796875 + ], + [ + 0.3203125, + 0.6875 + ], + [ + 0.328125, + 0.6953125 + ], + [ + 0.328125, + 0.703125 + ], + [ + 0.328125, + 0.6953125 + ], + [ + 0.3359375, + 0.6875 + ], + [ + 0.3359375, + 0.6796875 + ], + [ + 0.34375, + 0.671875 + ], + [ + 0.34375, + 0.6640625 + ], + [ + 0.3515625, + 0.65625 + ], + [ + 0.3515625, + 0.6484375 + ], + [ + 0.359375, + 0.640625 + ], + [ + 0.359375, + 0.6328125 + ], + [ + 0.3671875, + 0.625 + ], + [ + 0.3671875, + 0.6171875 + ], + [ + 0.375, + 0.609375 + ], + [ + 0.375, + 0.6015625 + ], + [ + 0.3828125, + 0.59375 + ], + [ + 0.3828125, + 0.5859375 + ], + [ + 0.390625, + 0.578125 + ], + [ + 0.390625, + 0.5703125 + ], + [ + 0.3984375, + 0.5625 + ], + [ + 0.3984375, + 0.5546875 + ], + [ + 0.40625, + 0.546875 + ], + [ + 0.40625, + 0.5390625 + ], + [ + 0.4140625, + 0.53125 + ], + [ + 0.4140625, + 0.5234375 + ], + [ + 0.4140625, + 0.515625 + ], + [ + 0.421875, + 0.5078125 + ], + [ + 0.4296875, + 0.5078125 + ], + [ + 0.4375, + 0.5078125 + ], + [ + 0.4453125, + 0.5078125 + ], + [ + 0.453125, + 0.5078125 + ], + [ + 0.4609375, + 0.5078125 + ], + [ + 0.46875, + 0.5078125 + ], + [ + 0.4765625, + 0.5 + ], + [ + 0.484375, + 0.5 + ], + [ + 0.4921875, + 0.5 + ], + [ + 0.5, + 0.5 + ], + [ + 0.5078125, + 0.5 + ], + [ + 0.515625, + 0.5 + ], + [ + 0.5234375, + 0.5 + ], + [ + 0.53125, + 0.4921875 + ], + [ + 0.5390625, + 0.4921875 + ], + [ + 0.546875, + 0.4921875 + ], + [ + 0.5546875, + 0.4921875 + ], + [ + 0.5625, + 0.4921875 + ], + [ + 0.5703125, + 0.4921875 + ], + [ + 0.578125, + 0.4921875 + ], + [ + 0.5859375, + 0.484375 + ], + [ + 0.59375, + 0.484375 + ], + [ + 0.6015625, + 0.484375 + ], + [ + 0.609375, + 0.4921875 + ], + [ + 0.609375, + 0.5 + ], + [ + 0.609375, + 0.5078125 + ], + [ + 0.6171875, + 0.515625 + ], + [ + 0.6171875, + 0.5234375 + ], + [ + 0.6171875, + 0.53125 + ], + [ + 0.6171875, + 0.5390625 + ], + [ + 0.6171875, + 0.546875 + ], + [ + 0.6171875, + 0.5546875 + ], + [ + 0.6171875, + 0.5625 + ], + [ + 0.625, + 0.5703125 + ], + [ + 0.625, + 0.578125 + ], + [ + 0.625, + 0.5859375 + ], + [ + 0.625, + 0.59375 + ], + [ + 0.625, + 0.6015625 + ], + [ + 0.625, + 0.609375 + ], + [ + 0.625, + 0.6171875 + ], + [ + 0.625, + 0.625 + ], + [ + 0.6171875, + 0.6328125 + ], + [ + 0.609375, + 0.640625 + ], + [ + 0.6015625, + 0.6484375 + ], + [ + 0.59375, + 0.65625 + ], + [ + 0.5859375, + 0.6640625 + ], + [ + 0.578125, + 0.671875 + ], + [ + 0.5703125, + 0.6796875 + ], + [ + 0.5625, + 0.6796875 + ], + [ + 0.5546875, + 0.6875 + ], + [ + 0.546875, + 0.6953125 + ], + [ + 0.5390625, + 0.703125 + ], + [ + 0.53125, + 0.7109375 + ], + [ + 0.5234375, + 0.71875 + ], + [ + 0.515625, + 0.7265625 + ], + [ + 0.5234375, + 0.7265625 + ], + [ + 0.53125, + 0.7265625 + ], + [ + 0.5390625, + 0.7265625 + ], + [ + 0.546875, + 0.7265625 + ], + [ + 0.5546875, + 0.7265625 + ], + [ + 0.5625, + 0.7265625 + ], + [ + 0.5703125, + 0.734375 + ], + [ + 0.578125, + 0.734375 + ], + [ + 0.5859375, + 0.734375 + ], + [ + 0.59375, + 0.734375 + ], + [ + 0.6015625, + 0.734375 + ], + [ + 0.609375, + 0.734375 + ], + [ + 0.6171875, + 0.734375 + ], + [ + 0.625, + 0.7421875 + ], + [ + 0.6328125, + 0.7421875 + ], + [ + 0.640625, + 0.7421875 + ], + [ + 0.6484375, + 0.7421875 + ], + [ + 0.65625, + 0.7421875 + ], + [ + 0.6640625, + 0.7421875 + ], + [ + 0.671875, + 0.7421875 + ], + [ + 0.6796875, + 0.75 + ], + [ + 0.6796875, + 0.7578125 + ], + [ + 0.6796875, + 0.765625 + ], + [ + 0.6875, + 0.7734375 + ], + [ + 0.6875, + 0.78125 + ], + [ + 0.6953125, + 0.7890625 + ], + [ + 0.6953125, + 0.796875 + ], + [ + 0.703125, + 0.8046875 + ], + [ + 0.703125, + 0.8125 + ], + [ + 0.7109375, + 0.8203125 + ], + [ + 0.7109375, + 0.828125 + ], + [ + 0.71875, + 0.8359375 + ], + [ + 0.71875, + 0.84375 + ], + [ + 0.7265625, + 0.8515625 + ], + [ + 0.7265625, + 0.859375 + ], + [ + 0.734375, + 0.8671875 + ], + [ + 0.734375, + 0.875 + ], + [ + 0.7421875, + 0.8828125 + ], + [ + 0.7421875, + 0.890625 + ], + [ + 0.7421875, + 0.8828125 + ], + [ + 0.75, + 0.875 + ], + [ + 0.75, + 0.8671875 + ], + [ + 0.7578125, + 0.859375 + ], + [ + 0.7578125, + 0.8515625 + ], + [ + 0.765625, + 0.84375 + ], + [ + 0.765625, + 0.8359375 + ], + [ + 0.7734375, + 0.828125 + ], + [ + 0.7734375, + 0.8203125 + ], + [ + 0.78125, + 0.8125 + ], + [ + 0.78125, + 0.8046875 + ], + [ + 0.7890625, + 0.796875 + ], + [ + 0.7890625, + 0.7890625 + ], + [ + 0.796875, + 0.78125 + ], + [ + 0.796875, + 0.7734375 + ], + [ + 0.8046875, + 0.765625 + ], + [ + 0.8046875, + 0.7578125 + ], + [ + 0.8046875, + 0.75 + ], + [ + 0.8125, + 0.7421875 + ], + [ + 0.8203125, + 0.7421875 + ], + [ + 0.828125, + 0.7421875 + ], + [ + 0.8359375, + 0.7421875 + ], + [ + 0.84375, + 0.7421875 + ], + [ + 0.8515625, + 0.7421875 + ], + [ + 0.859375, + 0.7421875 + ], + [ + 0.8671875, + 0.734375 + ], + [ + 0.875, + 0.734375 + ], + [ + 0.8828125, + 0.734375 + ], + [ + 0.890625, + 0.734375 + ], + [ + 0.8984375, + 0.734375 + ], + [ + 0.90625, + 0.734375 + ], + [ + 0.9140625, + 0.734375 + ], + [ + 0.921875, + 0.7265625 + ], + [ + 0.9296875, + 0.7265625 + ], + [ + 0.9375, + 0.7265625 + ], + [ + 0.9453125, + 0.7265625 + ], + [ + 0.953125, + 0.7265625 + ], + [ + 0.9609375, + 0.7265625 + ], + [ + 0.96875, + 0.7265625 + ], + [ + 0.9609375, + 0.71875 + ], + [ + 0.953125, + 0.7109375 + ], + [ + 0.9453125, + 0.703125 + ], + [ + 0.9375, + 0.6953125 + ], + [ + 0.9296875, + 0.6875 + ], + [ + 0.921875, + 0.6796875 + ], + [ + 0.9140625, + 0.6796875 + ], + [ + 0.90625, + 0.671875 + ], + [ + 0.8984375, + 0.6640625 + ], + [ + 0.890625, + 0.65625 + ], + [ + 0.8828125, + 0.6484375 + ], + [ + 0.875, + 0.640625 + ], + [ + 0.8671875, + 0.6328125 + ], + [ + 0.859375, + 0.625 + ], + [ + 0.859375, + 0.6171875 + ], + [ + 0.859375, + 0.609375 + ], + [ + 0.859375, + 0.6015625 + ], + [ + 0.859375, + 0.59375 + ], + [ + 0.859375, + 0.5859375 + ], + [ + 0.859375, + 0.578125 + ], + [ + 0.859375, + 0.5703125 + ], + [ + 0.8671875, + 0.5625 + ], + [ + 0.8671875, + 0.5546875 + ], + [ + 0.8671875, + 0.546875 + ], + [ + 0.8671875, + 0.5390625 + ], + [ + 0.8671875, + 0.53125 + ], + [ + 0.8671875, + 0.5234375 + ], + [ + 0.8671875, + 0.515625 + ], + [ + 0.875, + 0.5078125 + ], + [ + 0.875, + 0.5 + ], + [ + 0.875, + 0.4921875 + ], + [ + 0.875, + 0.484375 + ], + [ + 0.875, + 0.4765625 + ], + [ + 0.875, + 0.46875 + ], + [ + 0.8671875, + 0.46875 + ], + [ + 0.859375, + 0.4765625 + ], + [ + 0.8515625, + 0.4765625 + ], + [ + 0.84375, + 0.484375 + ], + [ + 0.8359375, + 0.484375 + ], + [ + 0.828125, + 0.4921875 + ], + [ + 0.8203125, + 0.4921875 + ], + [ + 0.8125, + 0.5 + ], + [ + 0.8046875, + 0.5 + ], + [ + 0.796875, + 0.5078125 + ], + [ + 0.7890625, + 0.5078125 + ], + [ + 0.78125, + 0.515625 + ], + [ + 0.7734375, + 0.515625 + ], + [ + 0.765625, + 0.5234375 + ], + [ + 0.7578125, + 0.5234375 + ], + [ + 0.75, + 0.53125 + ], + [ + 0.7421875, + 0.53125 + ], + [ + 0.734375, + 0.53125 + ], + [ + 0.7265625, + 0.5234375 + ], + [ + 0.71875, + 0.5234375 + ], + [ + 0.7109375, + 0.515625 + ], + [ + 0.703125, + 0.515625 + ], + [ + 0.6953125, + 0.5078125 + ], + [ + 0.6875, + 0.5078125 + ], + [ + 0.6796875, + 0.5 + ], + [ + 0.671875, + 0.5 + ], + [ + 0.6640625, + 0.4921875 + ], + [ + 0.65625, + 0.484375 + ], + [ + 0.65625, + 0.4765625 + ], + [ + 0.6640625, + 0.46875 + ], + [ + 0.6640625, + 0.4609375 + ], + [ + 0.671875, + 0.453125 + ], + [ + 0.6796875, + 0.453125 + ], + [ + 0.6875, + 0.453125 + ], + [ + 0.6953125, + 0.453125 + ], + [ + 0.703125, + 0.453125 + ], + [ + 0.7109375, + 0.453125 + ], + [ + 0.71875, + 0.4453125 + ], + [ + 0.7265625, + 0.4453125 + ], + [ + 0.734375, + 0.4453125 + ], + [ + 0.7421875, + 0.4453125 + ], + [ + 0.75, + 0.4453125 + ], + [ + 0.7578125, + 0.4453125 + ], + [ + 0.75, + 0.4375 + ], + [ + 0.7421875, + 0.4296875 + ], + [ + 0.734375, + 0.421875 + ], + [ + 0.7265625, + 0.421875 + ], + [ + 0.71875, + 0.4140625 + ], + [ + 0.7109375, + 0.40625 + ], + [ + 0.703125, + 0.3984375 + ], + [ + 0.6953125, + 0.390625 + ], + [ + 0.6953125, + 0.3828125 + ], + [ + 0.6953125, + 0.375 + ], + [ + 0.6953125, + 0.3671875 + ], + [ + 0.6953125, + 0.359375 + ], + [ + 0.6953125, + 0.3515625 + ], + [ + 0.6953125, + 0.34375 + ], + [ + 0.703125, + 0.3359375 + ], + [ + 0.703125, + 0.328125 + ], + [ + 0.703125, + 0.3203125 + ], + [ + 0.703125, + 0.3125 + ], + [ + 0.703125, + 0.3046875 + ], + [ + 0.6953125, + 0.3046875 + ], + [ + 0.6875, + 0.3125 + ], + [ + 0.6796875, + 0.3125 + ], + [ + 0.671875, + 0.3203125 + ], + [ + 0.6640625, + 0.3203125 + ], + [ + 0.65625, + 0.328125 + ], + [ + 0.6484375, + 0.328125 + ], + [ + 0.640625, + 0.3359375 + ], + [ + 0.6328125, + 0.3359375 + ], + [ + 0.625, + 0.3359375 + ], + [ + 0.6171875, + 0.328125 + ], + [ + 0.609375, + 0.328125 + ], + [ + 0.6015625, + 0.3203125 + ], + [ + 0.59375, + 0.3203125 + ], + [ + 0.5859375, + 0.3125 + ], + [ + 0.578125, + 0.3125 + ], + [ + 0.5703125, + 0.3046875 + ], + [ + 0.5625, + 0.3046875 + ], + [ + 0.5625, + 0.3125 + ], + [ + 0.5625, + 0.3203125 + ], + [ + 0.5625, + 0.328125 + ], + [ + 0.5625, + 0.3359375 + ], + [ + 0.5703125, + 0.34375 + ], + [ + 0.5703125, + 0.3515625 + ], + [ + 0.5703125, + 0.359375 + ], + [ + 0.5703125, + 0.3671875 + ], + [ + 0.5703125, + 0.375 + ], + [ + 0.5703125, + 0.3828125 + ], + [ + 0.5703125, + 0.390625 + ], + [ + 0.5625, + 0.3984375 + ], + [ + 0.5546875, + 0.40625 + ], + [ + 0.546875, + 0.4140625 + ], + [ + 0.5390625, + 0.40625 + ], + [ + 0.53125, + 0.3984375 + ], + [ + 0.5234375, + 0.390625 + ], + [ + 0.515625, + 0.3828125 + ], + [ + 0.5078125, + 0.375 + ], + [ + 0.5, + 0.3671875 + ], + [ + 0.4921875, + 0.359375 + ], + [ + 0.484375, + 0.3515625 + ], + [ + 0.4765625, + 0.34375 + ], + [ + 0.4765625, + 0.3359375 + ], + [ + 0.4765625, + 0.328125 + ], + [ + 0.4765625, + 0.3203125 + ], + [ + 0.4765625, + 0.3125 + ], + [ + 0.4765625, + 0.3046875 + ], + [ + 0.484375, + 0.296875 + ], + [ + 0.484375, + 0.2890625 + ], + [ + 0.484375, + 0.28125 + ], + [ + 0.484375, + 0.2734375 + ], + [ + 0.484375, + 0.265625 + ], + [ + 0.4921875, + 0.2578125 + ], + [ + 0.4921875, + 0.25 + ], + [ + 0.4921875, + 0.2421875 + ], + [ + 0.4921875, + 0.234375 + ], + [ + 0.4921875, + 0.2265625 + ], + [ + 0.4921875, + 0.21875 + ], + [ + 0.5, + 0.2109375 + ], + [ + 0.5, + 0.203125 + ], + [ + 0.5, + 0.1953125 + ], + [ + 0.5, + 0.1875 + ], + [ + 0.5, + 0.1796875 + ], + [ + 0.5078125, + 0.171875 + ], + [ + 0.5078125, + 0.1640625 + ], + [ + 0.5078125, + 0.15625 + ], + [ + 0.5078125, + 0.1484375 + ], + [ + 0.5078125, + 0.140625 + ], + [ + 0.5, + 0.140625 + ], + [ + 0.4921875, + 0.1484375 + ], + [ + 0.484375, + 0.1484375 + ], + [ + 0.4765625, + 0.15625 + ], + [ + 0.46875, + 0.15625 + ], + [ + 0.4609375, + 0.1640625 + ], + [ + 0.453125, + 0.1640625 + ], + [ + 0.4453125, + 0.171875 + ], + [ + 0.4375, + 0.171875 + ], + [ + 0.4296875, + 0.1796875 + ], + [ + 0.421875, + 0.1796875 + ], + [ + 0.4140625, + 0.1875 + ], + [ + 0.40625, + 0.1875 + ], + [ + 0.3984375, + 0.1953125 + ], + [ + 0.390625, + 0.1953125 + ], + [ + 0.3828125, + 0.203125 + ], + [ + 0.375, + 0.203125 + ], + [ + 0.3671875, + 0.2109375 + ], + [ + 0.359375, + 0.2109375 + ], + [ + 0.3515625, + 0.21875 + ], + [ + 0.34375, + 0.21875 + ], + [ + 0.3359375, + 0.2265625 + ], + [ + 0.328125, + 0.2265625 + ], + [ + 0.3203125, + 0.2265625 + ], + [ + 0.3125, + 0.21875 + ], + [ + 0.3046875, + 0.21875 + ], + [ + 0.296875, + 0.2109375 + ], + [ + 0.2890625, + 0.2109375 + ], + [ + 0.28125, + 0.203125 + ], + [ + 0.2734375, + 0.203125 + ], + [ + 0.265625, + 0.1953125 + ], + [ + 0.2578125, + 0.1953125 + ], + [ + 0.25, + 0.1875 + ], + [ + 0.2421875, + 0.1875 + ], + [ + 0.234375, + 0.1796875 + ], + [ + 0.2265625, + 0.1796875 + ], + [ + 0.21875, + 0.171875 + ], + [ + 0.2109375, + 0.171875 + ], + [ + 0.203125, + 0.1640625 + ], + [ + 0.1953125, + 0.1640625 + ], + [ + 0.1875, + 0.15625 + ], + [ + 0.1796875, + 0.15625 + ], + [ + 0.171875, + 0.1484375 + ], + [ + 0.1640625, + 0.1484375 + ], + [ + 0.15625, + 0.140625 + ] + ] + ], + "8": [ + [ + [ + 0.1796875, + 0.0859375 + ], + [ + 0.1796875, + 0.09375 + ], + [ + 0.1796875, + 0.1015625 + ], + [ + 0.1796875, + 0.109375 + ], + [ + 0.1796875, + 0.1171875 + ], + [ + 0.1875, + 0.125 + ], + [ + 0.1875, + 0.1328125 + ], + [ + 0.1875, + 0.140625 + ], + [ + 0.1875, + 0.1484375 + ], + [ + 0.1875, + 0.15625 + ], + [ + 0.1875, + 0.1640625 + ], + [ + 0.1953125, + 0.171875 + ], + [ + 0.1953125, + 0.1796875 + ], + [ + 0.1953125, + 0.1875 + ], + [ + 0.1953125, + 0.1953125 + ], + [ + 0.1953125, + 0.203125 + ], + [ + 0.203125, + 0.2109375 + ], + [ + 0.203125, + 0.21875 + ], + [ + 0.203125, + 0.2265625 + ], + [ + 0.203125, + 0.234375 + ], + [ + 0.203125, + 0.2421875 + ], + [ + 0.203125, + 0.25 + ], + [ + 0.2109375, + 0.2578125 + ], + [ + 0.2109375, + 0.265625 + ], + [ + 0.2109375, + 0.2734375 + ], + [ + 0.2109375, + 0.28125 + ], + [ + 0.2109375, + 0.2890625 + ], + [ + 0.2109375, + 0.296875 + ], + [ + 0.21875, + 0.3046875 + ], + [ + 0.21875, + 0.3125 + ], + [ + 0.21875, + 0.3203125 + ], + [ + 0.21875, + 0.328125 + ], + [ + 0.21875, + 0.3359375 + ], + [ + 0.21875, + 0.34375 + ], + [ + 0.2109375, + 0.3515625 + ], + [ + 0.203125, + 0.359375 + ], + [ + 0.1953125, + 0.3671875 + ], + [ + 0.1875, + 0.375 + ], + [ + 0.1796875, + 0.3828125 + ], + [ + 0.171875, + 0.390625 + ], + [ + 0.1640625, + 0.3984375 + ], + [ + 0.15625, + 0.40625 + ], + [ + 0.1484375, + 0.4140625 + ], + [ + 0.140625, + 0.421875 + ], + [ + 0.1328125, + 0.4296875 + ], + [ + 0.125, + 0.4375 + ], + [ + 0.1171875, + 0.4453125 + ], + [ + 0.109375, + 0.453125 + ], + [ + 0.1015625, + 0.4609375 + ], + [ + 0.09375, + 0.46875 + ], + [ + 0.0859375, + 0.4765625 + ], + [ + 0.078125, + 0.484375 + ], + [ + 0.0703125, + 0.4921875 + ], + [ + 0.0625, + 0.5 + ], + [ + 0.0546875, + 0.5078125 + ], + [ + 0.046875, + 0.515625 + ], + [ + 0.0390625, + 0.5234375 + ], + [ + 0.03125, + 0.53125 + ], + [ + 0.0390625, + 0.53125 + ], + [ + 0.046875, + 0.53125 + ], + [ + 0.0546875, + 0.53125 + ], + [ + 0.0625, + 0.53125 + ], + [ + 0.0703125, + 0.53125 + ], + [ + 0.078125, + 0.5390625 + ], + [ + 0.0859375, + 0.5390625 + ], + [ + 0.09375, + 0.5390625 + ], + [ + 0.1015625, + 0.5390625 + ], + [ + 0.109375, + 0.5390625 + ], + [ + 0.1171875, + 0.5390625 + ], + [ + 0.125, + 0.5390625 + ], + [ + 0.1328125, + 0.546875 + ], + [ + 0.140625, + 0.546875 + ], + [ + 0.1484375, + 0.546875 + ], + [ + 0.15625, + 0.546875 + ], + [ + 0.1640625, + 0.546875 + ], + [ + 0.171875, + 0.546875 + ], + [ + 0.1796875, + 0.546875 + ], + [ + 0.1875, + 0.5546875 + ], + [ + 0.1953125, + 0.5546875 + ], + [ + 0.203125, + 0.5546875 + ], + [ + 0.2109375, + 0.5546875 + ], + [ + 0.21875, + 0.5546875 + ], + [ + 0.2265625, + 0.5546875 + ], + [ + 0.234375, + 0.5546875 + ], + [ + 0.2421875, + 0.5625 + ], + [ + 0.25, + 0.5625 + ], + [ + 0.2578125, + 0.5625 + ], + [ + 0.265625, + 0.5625 + ], + [ + 0.2734375, + 0.5625 + ], + [ + 0.28125, + 0.5625 + ], + [ + 0.2890625, + 0.5625 + ], + [ + 0.296875, + 0.5703125 + ], + [ + 0.296875, + 0.578125 + ], + [ + 0.3046875, + 0.5859375 + ], + [ + 0.3046875, + 0.59375 + ], + [ + 0.3125, + 0.6015625 + ], + [ + 0.3125, + 0.609375 + ], + [ + 0.3203125, + 0.6171875 + ], + [ + 0.3203125, + 0.625 + ], + [ + 0.328125, + 0.6328125 + ], + [ + 0.328125, + 0.640625 + ], + [ + 0.3359375, + 0.6484375 + ], + [ + 0.3359375, + 0.65625 + ], + [ + 0.34375, + 0.6640625 + ], + [ + 0.34375, + 0.671875 + ], + [ + 0.3515625, + 0.6796875 + ], + [ + 0.3515625, + 0.6875 + ], + [ + 0.359375, + 0.6953125 + ], + [ + 0.359375, + 0.703125 + ], + [ + 0.3671875, + 0.7109375 + ], + [ + 0.3671875, + 0.71875 + ], + [ + 0.375, + 0.7265625 + ], + [ + 0.375, + 0.734375 + ], + [ + 0.3828125, + 0.7421875 + ], + [ + 0.3828125, + 0.75 + ], + [ + 0.390625, + 0.7578125 + ], + [ + 0.390625, + 0.765625 + ], + [ + 0.3984375, + 0.7734375 + ], + [ + 0.3984375, + 0.78125 + ], + [ + 0.40625, + 0.7890625 + ], + [ + 0.40625, + 0.796875 + ], + [ + 0.40625, + 0.7890625 + ], + [ + 0.4140625, + 0.78125 + ], + [ + 0.4140625, + 0.7734375 + ], + [ + 0.421875, + 0.765625 + ], + [ + 0.421875, + 0.7578125 + ], + [ + 0.4296875, + 0.75 + ], + [ + 0.4296875, + 0.7421875 + ], + [ + 0.4375, + 0.734375 + ], + [ + 0.4375, + 0.7265625 + ], + [ + 0.4453125, + 0.71875 + ], + [ + 0.4453125, + 0.7109375 + ], + [ + 0.453125, + 0.703125 + ], + [ + 0.453125, + 0.6953125 + ], + [ + 0.4609375, + 0.6875 + ], + [ + 0.46875, + 0.6875 + ], + [ + 0.4765625, + 0.6875 + ], + [ + 0.484375, + 0.6875 + ], + [ + 0.4921875, + 0.6875 + ], + [ + 0.5, + 0.6953125 + ], + [ + 0.5078125, + 0.6953125 + ], + [ + 0.515625, + 0.6953125 + ], + [ + 0.5234375, + 0.6953125 + ], + [ + 0.53125, + 0.6953125 + ], + [ + 0.5390625, + 0.6953125 + ], + [ + 0.546875, + 0.6953125 + ], + [ + 0.5546875, + 0.6953125 + ], + [ + 0.5625, + 0.703125 + ], + [ + 0.5703125, + 0.703125 + ], + [ + 0.578125, + 0.703125 + ], + [ + 0.5859375, + 0.703125 + ], + [ + 0.59375, + 0.703125 + ], + [ + 0.6015625, + 0.703125 + ], + [ + 0.609375, + 0.7109375 + ], + [ + 0.609375, + 0.71875 + ], + [ + 0.6171875, + 0.7265625 + ], + [ + 0.6171875, + 0.734375 + ], + [ + 0.6171875, + 0.7265625 + ], + [ + 0.625, + 0.71875 + ], + [ + 0.6328125, + 0.7265625 + ], + [ + 0.640625, + 0.734375 + ], + [ + 0.640625, + 0.7421875 + ], + [ + 0.6484375, + 0.75 + ], + [ + 0.6484375, + 0.7578125 + ], + [ + 0.65625, + 0.765625 + ], + [ + 0.65625, + 0.7734375 + ], + [ + 0.6640625, + 0.78125 + ], + [ + 0.6640625, + 0.7890625 + ], + [ + 0.671875, + 0.796875 + ], + [ + 0.671875, + 0.8046875 + ], + [ + 0.671875, + 0.8125 + ], + [ + 0.6796875, + 0.8203125 + ], + [ + 0.6796875, + 0.828125 + ], + [ + 0.6875, + 0.8359375 + ], + [ + 0.6875, + 0.84375 + ], + [ + 0.6953125, + 0.8515625 + ], + [ + 0.6953125, + 0.859375 + ], + [ + 0.703125, + 0.8671875 + ], + [ + 0.703125, + 0.875 + ], + [ + 0.703125, + 0.8671875 + ], + [ + 0.7109375, + 0.859375 + ], + [ + 0.7109375, + 0.8515625 + ], + [ + 0.71875, + 0.84375 + ], + [ + 0.71875, + 0.8359375 + ], + [ + 0.7265625, + 0.828125 + ], + [ + 0.7265625, + 0.8203125 + ], + [ + 0.734375, + 0.8125 + ], + [ + 0.734375, + 0.8046875 + ], + [ + 0.734375, + 0.796875 + ], + [ + 0.7421875, + 0.7890625 + ], + [ + 0.7421875, + 0.78125 + ], + [ + 0.75, + 0.7734375 + ], + [ + 0.75, + 0.765625 + ], + [ + 0.7578125, + 0.7578125 + ], + [ + 0.7578125, + 0.75 + ], + [ + 0.765625, + 0.7421875 + ], + [ + 0.765625, + 0.734375 + ], + [ + 0.7734375, + 0.7265625 + ], + [ + 0.7734375, + 0.71875 + ], + [ + 0.7734375, + 0.7109375 + ], + [ + 0.78125, + 0.703125 + ], + [ + 0.7890625, + 0.703125 + ], + [ + 0.796875, + 0.703125 + ], + [ + 0.8046875, + 0.703125 + ], + [ + 0.8125, + 0.703125 + ], + [ + 0.8203125, + 0.703125 + ], + [ + 0.828125, + 0.703125 + ], + [ + 0.8359375, + 0.703125 + ], + [ + 0.84375, + 0.703125 + ], + [ + 0.8515625, + 0.6953125 + ], + [ + 0.859375, + 0.6953125 + ], + [ + 0.8671875, + 0.6953125 + ], + [ + 0.875, + 0.6953125 + ], + [ + 0.8828125, + 0.6953125 + ], + [ + 0.890625, + 0.6953125 + ], + [ + 0.8984375, + 0.6953125 + ], + [ + 0.90625, + 0.6953125 + ], + [ + 0.9140625, + 0.6875 + ], + [ + 0.921875, + 0.6875 + ], + [ + 0.9296875, + 0.6875 + ], + [ + 0.9375, + 0.6875 + ], + [ + 0.9453125, + 0.6875 + ], + [ + 0.953125, + 0.6875 + ], + [ + 0.9609375, + 0.6875 + ], + [ + 0.96875, + 0.6875 + ], + [ + 0.9609375, + 0.6796875 + ], + [ + 0.953125, + 0.671875 + ], + [ + 0.9453125, + 0.6640625 + ], + [ + 0.9375, + 0.65625 + ], + [ + 0.9296875, + 0.6484375 + ], + [ + 0.921875, + 0.640625 + ], + [ + 0.9140625, + 0.6328125 + ], + [ + 0.90625, + 0.625 + ], + [ + 0.8984375, + 0.625 + ], + [ + 0.890625, + 0.6171875 + ], + [ + 0.8828125, + 0.609375 + ], + [ + 0.875, + 0.6015625 + ], + [ + 0.8671875, + 0.59375 + ], + [ + 0.859375, + 0.5859375 + ], + [ + 0.8515625, + 0.578125 + ], + [ + 0.84375, + 0.5703125 + ], + [ + 0.8359375, + 0.5625 + ], + [ + 0.8359375, + 0.5546875 + ], + [ + 0.8359375, + 0.546875 + ], + [ + 0.8359375, + 0.5390625 + ], + [ + 0.8359375, + 0.53125 + ], + [ + 0.8359375, + 0.5234375 + ], + [ + 0.8359375, + 0.515625 + ], + [ + 0.84375, + 0.5078125 + ], + [ + 0.8515625, + 0.5 + ], + [ + 0.859375, + 0.5 + ], + [ + 0.8671875, + 0.5 + ], + [ + 0.875, + 0.4921875 + ], + [ + 0.8828125, + 0.4921875 + ], + [ + 0.890625, + 0.4921875 + ], + [ + 0.8984375, + 0.4921875 + ], + [ + 0.90625, + 0.4921875 + ], + [ + 0.9140625, + 0.4921875 + ], + [ + 0.921875, + 0.484375 + ], + [ + 0.9296875, + 0.484375 + ], + [ + 0.9375, + 0.484375 + ], + [ + 0.9453125, + 0.484375 + ], + [ + 0.953125, + 0.484375 + ], + [ + 0.9609375, + 0.484375 + ], + [ + 0.953125, + 0.4765625 + ], + [ + 0.9453125, + 0.46875 + ], + [ + 0.9375, + 0.4609375 + ], + [ + 0.9296875, + 0.453125 + ], + [ + 0.921875, + 0.4453125 + ], + [ + 0.9140625, + 0.4375 + ], + [ + 0.90625, + 0.4296875 + ], + [ + 0.8984375, + 0.421875 + ], + [ + 0.890625, + 0.4140625 + ], + [ + 0.8828125, + 0.40625 + ], + [ + 0.875, + 0.40625 + ], + [ + 0.8671875, + 0.3984375 + ], + [ + 0.859375, + 0.390625 + ], + [ + 0.859375, + 0.3828125 + ], + [ + 0.8515625, + 0.3828125 + ], + [ + 0.84375, + 0.375 + ], + [ + 0.8359375, + 0.3671875 + ], + [ + 0.828125, + 0.359375 + ], + [ + 0.8203125, + 0.3515625 + ], + [ + 0.8125, + 0.34375 + ], + [ + 0.8046875, + 0.3359375 + ], + [ + 0.796875, + 0.328125 + ], + [ + 0.7890625, + 0.3203125 + ], + [ + 0.7890625, + 0.3125 + ], + [ + 0.7890625, + 0.3046875 + ], + [ + 0.7890625, + 0.296875 + ], + [ + 0.7890625, + 0.2890625 + ], + [ + 0.7890625, + 0.28125 + ], + [ + 0.796875, + 0.2734375 + ], + [ + 0.796875, + 0.265625 + ], + [ + 0.796875, + 0.2578125 + ], + [ + 0.796875, + 0.25 + ], + [ + 0.796875, + 0.2421875 + ], + [ + 0.8046875, + 0.234375 + ], + [ + 0.8046875, + 0.2265625 + ], + [ + 0.8046875, + 0.21875 + ], + [ + 0.8046875, + 0.2109375 + ], + [ + 0.8046875, + 0.203125 + ], + [ + 0.8125, + 0.1953125 + ], + [ + 0.8125, + 0.1875 + ], + [ + 0.8125, + 0.1796875 + ], + [ + 0.8125, + 0.171875 + ], + [ + 0.8125, + 0.1640625 + ], + [ + 0.8203125, + 0.15625 + ], + [ + 0.8203125, + 0.1484375 + ], + [ + 0.8203125, + 0.140625 + ], + [ + 0.8203125, + 0.1328125 + ], + [ + 0.8203125, + 0.125 + ], + [ + 0.828125, + 0.1171875 + ], + [ + 0.828125, + 0.109375 + ], + [ + 0.828125, + 0.1015625 + ], + [ + 0.828125, + 0.09375 + ], + [ + 0.828125, + 0.0859375 + ], + [ + 0.8203125, + 0.0859375 + ], + [ + 0.8125, + 0.09375 + ], + [ + 0.8046875, + 0.09375 + ], + [ + 0.796875, + 0.1015625 + ], + [ + 0.7890625, + 0.1015625 + ], + [ + 0.78125, + 0.109375 + ], + [ + 0.7734375, + 0.109375 + ], + [ + 0.765625, + 0.1171875 + ], + [ + 0.7578125, + 0.1171875 + ], + [ + 0.75, + 0.125 + ], + [ + 0.7421875, + 0.125 + ], + [ + 0.734375, + 0.1328125 + ], + [ + 0.7265625, + 0.1328125 + ], + [ + 0.71875, + 0.140625 + ], + [ + 0.7109375, + 0.140625 + ], + [ + 0.703125, + 0.1484375 + ], + [ + 0.6953125, + 0.1484375 + ], + [ + 0.6875, + 0.15625 + ], + [ + 0.6796875, + 0.15625 + ], + [ + 0.671875, + 0.1640625 + ], + [ + 0.6640625, + 0.1640625 + ], + [ + 0.65625, + 0.171875 + ], + [ + 0.6484375, + 0.171875 + ], + [ + 0.640625, + 0.1796875 + ], + [ + 0.6328125, + 0.1796875 + ], + [ + 0.625, + 0.1875 + ], + [ + 0.6171875, + 0.1796875 + ], + [ + 0.6171875, + 0.171875 + ], + [ + 0.625, + 0.1640625 + ], + [ + 0.625, + 0.15625 + ], + [ + 0.625, + 0.1484375 + ], + [ + 0.625, + 0.140625 + ], + [ + 0.625, + 0.1328125 + ], + [ + 0.625, + 0.125 + ], + [ + 0.6328125, + 0.1171875 + ], + [ + 0.6328125, + 0.109375 + ], + [ + 0.6328125, + 0.1015625 + ], + [ + 0.6328125, + 0.09375 + ], + [ + 0.6328125, + 0.0859375 + ], + [ + 0.625, + 0.09375 + ], + [ + 0.6171875, + 0.09375 + ], + [ + 0.609375, + 0.1015625 + ], + [ + 0.6015625, + 0.1015625 + ], + [ + 0.59375, + 0.109375 + ], + [ + 0.5859375, + 0.109375 + ], + [ + 0.578125, + 0.1171875 + ], + [ + 0.5703125, + 0.1171875 + ], + [ + 0.5625, + 0.125 + ], + [ + 0.5546875, + 0.125 + ], + [ + 0.546875, + 0.1328125 + ], + [ + 0.5390625, + 0.1328125 + ], + [ + 0.53125, + 0.140625 + ], + [ + 0.5234375, + 0.140625 + ], + [ + 0.515625, + 0.140625 + ], + [ + 0.5078125, + 0.1328125 + ], + [ + 0.5, + 0.1328125 + ], + [ + 0.4921875, + 0.125 + ], + [ + 0.484375, + 0.125 + ], + [ + 0.4765625, + 0.1171875 + ], + [ + 0.46875, + 0.1171875 + ], + [ + 0.4609375, + 0.109375 + ], + [ + 0.453125, + 0.109375 + ], + [ + 0.4453125, + 0.1015625 + ], + [ + 0.4375, + 0.1015625 + ], + [ + 0.4296875, + 0.09375 + ], + [ + 0.421875, + 0.09375 + ], + [ + 0.4140625, + 0.0859375 + ], + [ + 0.40625, + 0.0859375 + ], + [ + 0.40625, + 0.09375 + ], + [ + 0.40625, + 0.1015625 + ], + [ + 0.40625, + 0.109375 + ], + [ + 0.40625, + 0.1171875 + ], + [ + 0.4140625, + 0.125 + ], + [ + 0.4140625, + 0.1328125 + ], + [ + 0.4140625, + 0.140625 + ], + [ + 0.4140625, + 0.1484375 + ], + [ + 0.4140625, + 0.15625 + ], + [ + 0.421875, + 0.1640625 + ], + [ + 0.421875, + 0.171875 + ], + [ + 0.421875, + 0.1796875 + ], + [ + 0.421875, + 0.1875 + ], + [ + 0.421875, + 0.1953125 + ], + [ + 0.4140625, + 0.203125 + ], + [ + 0.40625, + 0.203125 + ], + [ + 0.3984375, + 0.203125 + ], + [ + 0.390625, + 0.1953125 + ], + [ + 0.3828125, + 0.1953125 + ], + [ + 0.375, + 0.1875 + ], + [ + 0.3671875, + 0.1875 + ], + [ + 0.359375, + 0.1796875 + ], + [ + 0.3515625, + 0.1796875 + ], + [ + 0.34375, + 0.171875 + ], + [ + 0.3359375, + 0.171875 + ], + [ + 0.328125, + 0.1640625 + ], + [ + 0.3203125, + 0.1640625 + ], + [ + 0.3125, + 0.15625 + ], + [ + 0.3046875, + 0.15625 + ], + [ + 0.296875, + 0.1484375 + ], + [ + 0.2890625, + 0.140625 + ], + [ + 0.28125, + 0.140625 + ], + [ + 0.2734375, + 0.1328125 + ], + [ + 0.265625, + 0.1328125 + ], + [ + 0.2578125, + 0.125 + ], + [ + 0.25, + 0.125 + ], + [ + 0.2421875, + 0.1171875 + ], + [ + 0.234375, + 0.1171875 + ], + [ + 0.2265625, + 0.109375 + ], + [ + 0.21875, + 0.109375 + ], + [ + 0.2109375, + 0.1015625 + ], + [ + 0.203125, + 0.1015625 + ], + [ + 0.1953125, + 0.09375 + ], + [ + 0.1875, + 0.09375 + ] + ], + [ + [ + 0.515625, + 0.5703125 + ], + [ + 0.5234375, + 0.5625 + ], + [ + 0.53125, + 0.5625 + ], + [ + 0.5390625, + 0.5703125 + ], + [ + 0.5390625, + 0.578125 + ], + [ + 0.546875, + 0.5859375 + ], + [ + 0.5390625, + 0.59375 + ], + [ + 0.53125, + 0.6015625 + ], + [ + 0.5234375, + 0.609375 + ], + [ + 0.515625, + 0.6171875 + ], + [ + 0.5078125, + 0.625 + ], + [ + 0.5, + 0.625 + ], + [ + 0.4921875, + 0.6171875 + ], + [ + 0.5, + 0.609375 + ], + [ + 0.5, + 0.6015625 + ], + [ + 0.5078125, + 0.59375 + ], + [ + 0.5078125, + 0.5859375 + ], + [ + 0.515625, + 0.578125 + ] + ] + ], + "9": [ + [ + [ + 0.1796875, + 0.0 + ], + [ + 0.1796875, + 0.0078125 + ], + [ + 0.171875, + 0.015625 + ], + [ + 0.171875, + 0.0234375 + ], + [ + 0.1640625, + 0.03125 + ], + [ + 0.1640625, + 0.0390625 + ], + [ + 0.15625, + 0.046875 + ], + [ + 0.1484375, + 0.0546875 + ], + [ + 0.1484375, + 0.0625 + ], + [ + 0.140625, + 0.0703125 + ], + [ + 0.140625, + 0.078125 + ], + [ + 0.1328125, + 0.0859375 + ], + [ + 0.125, + 0.09375 + ], + [ + 0.125, + 0.1015625 + ], + [ + 0.1171875, + 0.109375 + ], + [ + 0.1171875, + 0.1171875 + ], + [ + 0.109375, + 0.125 + ], + [ + 0.1015625, + 0.1328125 + ], + [ + 0.1015625, + 0.140625 + ], + [ + 0.09375, + 0.1484375 + ], + [ + 0.09375, + 0.15625 + ], + [ + 0.0859375, + 0.1640625 + ], + [ + 0.0859375, + 0.171875 + ], + [ + 0.078125, + 0.1796875 + ], + [ + 0.0703125, + 0.1875 + ], + [ + 0.0703125, + 0.1953125 + ], + [ + 0.0625, + 0.203125 + ], + [ + 0.0625, + 0.2109375 + ], + [ + 0.0546875, + 0.21875 + ], + [ + 0.046875, + 0.2265625 + ], + [ + 0.046875, + 0.234375 + ], + [ + 0.0390625, + 0.2421875 + ], + [ + 0.0390625, + 0.25 + ], + [ + 0.03125, + 0.2578125 + ], + [ + 0.0234375, + 0.265625 + ], + [ + 0.0234375, + 0.2734375 + ], + [ + 0.015625, + 0.28125 + ], + [ + 0.015625, + 0.2890625 + ], + [ + 0.0078125, + 0.296875 + ], + [ + 0.0078125, + 0.3046875 + ], + [ + 0.0078125, + 0.3125 + ], + [ + 0.015625, + 0.3203125 + ], + [ + 0.015625, + 0.328125 + ], + [ + 0.0234375, + 0.3359375 + ], + [ + 0.0234375, + 0.34375 + ], + [ + 0.03125, + 0.3515625 + ], + [ + 0.0390625, + 0.359375 + ], + [ + 0.0390625, + 0.3671875 + ], + [ + 0.046875, + 0.375 + ], + [ + 0.046875, + 0.3828125 + ], + [ + 0.0546875, + 0.390625 + ], + [ + 0.0546875, + 0.3984375 + ], + [ + 0.0625, + 0.40625 + ], + [ + 0.0703125, + 0.4140625 + ], + [ + 0.0703125, + 0.421875 + ], + [ + 0.0625, + 0.4296875 + ], + [ + 0.0546875, + 0.4375 + ], + [ + 0.0546875, + 0.4453125 + ], + [ + 0.046875, + 0.453125 + ], + [ + 0.046875, + 0.4609375 + ], + [ + 0.0390625, + 0.46875 + ], + [ + 0.0390625, + 0.4765625 + ], + [ + 0.03125, + 0.484375 + ], + [ + 0.0234375, + 0.4921875 + ], + [ + 0.0234375, + 0.5 + ], + [ + 0.015625, + 0.5078125 + ], + [ + 0.015625, + 0.515625 + ], + [ + 0.0078125, + 0.5234375 + ], + [ + 0.0078125, + 0.53125 + ], + [ + 0.0078125, + 0.5390625 + ], + [ + 0.015625, + 0.546875 + ], + [ + 0.015625, + 0.5546875 + ], + [ + 0.0234375, + 0.5625 + ], + [ + 0.0234375, + 0.5703125 + ], + [ + 0.03125, + 0.578125 + ], + [ + 0.0390625, + 0.5859375 + ], + [ + 0.0390625, + 0.59375 + ], + [ + 0.046875, + 0.6015625 + ], + [ + 0.046875, + 0.609375 + ], + [ + 0.0546875, + 0.6171875 + ], + [ + 0.0546875, + 0.625 + ], + [ + 0.0625, + 0.6328125 + ], + [ + 0.0703125, + 0.640625 + ], + [ + 0.0703125, + 0.6484375 + ], + [ + 0.078125, + 0.65625 + ], + [ + 0.078125, + 0.6640625 + ], + [ + 0.0859375, + 0.671875 + ], + [ + 0.0859375, + 0.6796875 + ], + [ + 0.09375, + 0.6875 + ], + [ + 0.1015625, + 0.6953125 + ], + [ + 0.1015625, + 0.703125 + ], + [ + 0.109375, + 0.7109375 + ], + [ + 0.109375, + 0.71875 + ], + [ + 0.1171875, + 0.7265625 + ], + [ + 0.125, + 0.734375 + ], + [ + 0.125, + 0.7421875 + ], + [ + 0.1328125, + 0.75 + ], + [ + 0.1328125, + 0.7578125 + ], + [ + 0.140625, + 0.765625 + ], + [ + 0.140625, + 0.7734375 + ], + [ + 0.1484375, + 0.78125 + ], + [ + 0.15625, + 0.7890625 + ], + [ + 0.15625, + 0.796875 + ], + [ + 0.1640625, + 0.8046875 + ], + [ + 0.1640625, + 0.8125 + ], + [ + 0.171875, + 0.8203125 + ], + [ + 0.171875, + 0.828125 + ], + [ + 0.1796875, + 0.8359375 + ], + [ + 0.1875, + 0.84375 + ], + [ + 0.1875, + 0.8515625 + ], + [ + 0.1953125, + 0.859375 + ], + [ + 0.1953125, + 0.8671875 + ], + [ + 0.203125, + 0.875 + ], + [ + 0.2109375, + 0.875 + ], + [ + 0.21875, + 0.875 + ], + [ + 0.2265625, + 0.875 + ], + [ + 0.234375, + 0.875 + ], + [ + 0.2421875, + 0.875 + ], + [ + 0.25, + 0.875 + ], + [ + 0.2578125, + 0.875 + ], + [ + 0.265625, + 0.875 + ], + [ + 0.2734375, + 0.875 + ], + [ + 0.28125, + 0.875 + ], + [ + 0.2890625, + 0.875 + ], + [ + 0.296875, + 0.875 + ], + [ + 0.3046875, + 0.875 + ], + [ + 0.3125, + 0.875 + ], + [ + 0.3203125, + 0.875 + ], + [ + 0.328125, + 0.875 + ], + [ + 0.3359375, + 0.875 + ], + [ + 0.34375, + 0.875 + ], + [ + 0.3515625, + 0.875 + ], + [ + 0.359375, + 0.875 + ], + [ + 0.3671875, + 0.875 + ], + [ + 0.375, + 0.875 + ], + [ + 0.3828125, + 0.875 + ], + [ + 0.390625, + 0.875 + ], + [ + 0.3984375, + 0.875 + ], + [ + 0.40625, + 0.875 + ], + [ + 0.4140625, + 0.875 + ], + [ + 0.421875, + 0.875 + ], + [ + 0.4296875, + 0.875 + ], + [ + 0.4375, + 0.875 + ], + [ + 0.4453125, + 0.875 + ], + [ + 0.453125, + 0.875 + ], + [ + 0.4609375, + 0.875 + ], + [ + 0.46875, + 0.875 + ], + [ + 0.4765625, + 0.875 + ], + [ + 0.484375, + 0.875 + ], + [ + 0.4921875, + 0.875 + ], + [ + 0.5, + 0.875 + ], + [ + 0.5078125, + 0.875 + ], + [ + 0.515625, + 0.875 + ], + [ + 0.5234375, + 0.875 + ], + [ + 0.53125, + 0.875 + ], + [ + 0.5390625, + 0.875 + ], + [ + 0.546875, + 0.875 + ], + [ + 0.5546875, + 0.875 + ], + [ + 0.5625, + 0.875 + ], + [ + 0.5703125, + 0.875 + ], + [ + 0.578125, + 0.875 + ], + [ + 0.5859375, + 0.875 + ], + [ + 0.59375, + 0.875 + ], + [ + 0.6015625, + 0.875 + ], + [ + 0.609375, + 0.875 + ], + [ + 0.6171875, + 0.8671875 + ], + [ + 0.6171875, + 0.859375 + ], + [ + 0.625, + 0.8515625 + ], + [ + 0.625, + 0.84375 + ], + [ + 0.6328125, + 0.8359375 + ], + [ + 0.640625, + 0.828125 + ], + [ + 0.640625, + 0.8203125 + ], + [ + 0.6484375, + 0.8125 + ], + [ + 0.6484375, + 0.8046875 + ], + [ + 0.65625, + 0.796875 + ], + [ + 0.65625, + 0.7890625 + ], + [ + 0.6640625, + 0.78125 + ], + [ + 0.671875, + 0.7734375 + ], + [ + 0.671875, + 0.765625 + ], + [ + 0.6796875, + 0.7578125 + ], + [ + 0.6875, + 0.75 + ], + [ + 0.6953125, + 0.75 + ], + [ + 0.703125, + 0.75 + ], + [ + 0.7109375, + 0.75 + ], + [ + 0.71875, + 0.75 + ], + [ + 0.7265625, + 0.75 + ], + [ + 0.734375, + 0.75 + ], + [ + 0.7421875, + 0.75 + ], + [ + 0.75, + 0.75 + ], + [ + 0.7578125, + 0.75 + ], + [ + 0.765625, + 0.75 + ], + [ + 0.7734375, + 0.75 + ], + [ + 0.78125, + 0.75 + ], + [ + 0.7890625, + 0.75 + ], + [ + 0.796875, + 0.75 + ], + [ + 0.8046875, + 0.75 + ], + [ + 0.8125, + 0.7421875 + ], + [ + 0.8125, + 0.734375 + ], + [ + 0.8203125, + 0.7265625 + ], + [ + 0.8203125, + 0.71875 + ], + [ + 0.828125, + 0.7109375 + ], + [ + 0.828125, + 0.703125 + ], + [ + 0.8359375, + 0.6953125 + ], + [ + 0.84375, + 0.6875 + ], + [ + 0.84375, + 0.6796875 + ], + [ + 0.8515625, + 0.671875 + ], + [ + 0.8515625, + 0.6640625 + ], + [ + 0.859375, + 0.65625 + ], + [ + 0.859375, + 0.6484375 + ], + [ + 0.8671875, + 0.640625 + ], + [ + 0.875, + 0.6328125 + ], + [ + 0.875, + 0.625 + ], + [ + 0.8828125, + 0.6171875 + ], + [ + 0.8828125, + 0.609375 + ], + [ + 0.890625, + 0.6015625 + ], + [ + 0.890625, + 0.59375 + ], + [ + 0.8984375, + 0.5859375 + ], + [ + 0.90625, + 0.578125 + ], + [ + 0.90625, + 0.5703125 + ], + [ + 0.9140625, + 0.5625 + ], + [ + 0.9140625, + 0.5546875 + ], + [ + 0.921875, + 0.546875 + ], + [ + 0.921875, + 0.5390625 + ], + [ + 0.9296875, + 0.53125 + ], + [ + 0.9375, + 0.5234375 + ], + [ + 0.9375, + 0.515625 + ], + [ + 0.9453125, + 0.5078125 + ], + [ + 0.9453125, + 0.5 + ], + [ + 0.953125, + 0.4921875 + ], + [ + 0.953125, + 0.484375 + ], + [ + 0.9609375, + 0.4765625 + ], + [ + 0.96875, + 0.46875 + ], + [ + 0.96875, + 0.4609375 + ], + [ + 0.9765625, + 0.453125 + ], + [ + 0.9765625, + 0.4453125 + ], + [ + 0.984375, + 0.4375 + ], + [ + 0.984375, + 0.4296875 + ], + [ + 0.984375, + 0.421875 + ], + [ + 0.9765625, + 0.4140625 + ], + [ + 0.9765625, + 0.40625 + ], + [ + 0.96875, + 0.3984375 + ], + [ + 0.96875, + 0.390625 + ], + [ + 0.9609375, + 0.3828125 + ], + [ + 0.953125, + 0.375 + ], + [ + 0.953125, + 0.3671875 + ], + [ + 0.9453125, + 0.359375 + ], + [ + 0.9453125, + 0.3515625 + ], + [ + 0.9375, + 0.34375 + ], + [ + 0.9296875, + 0.3359375 + ], + [ + 0.9296875, + 0.328125 + ], + [ + 0.921875, + 0.3203125 + ], + [ + 0.921875, + 0.3125 + ], + [ + 0.9140625, + 0.3046875 + ], + [ + 0.9140625, + 0.296875 + ], + [ + 0.90625, + 0.2890625 + ], + [ + 0.8984375, + 0.28125 + ], + [ + 0.8984375, + 0.2734375 + ], + [ + 0.890625, + 0.265625 + ], + [ + 0.890625, + 0.2578125 + ], + [ + 0.8828125, + 0.25 + ], + [ + 0.875, + 0.2421875 + ], + [ + 0.875, + 0.234375 + ], + [ + 0.8671875, + 0.2265625 + ], + [ + 0.8671875, + 0.21875 + ], + [ + 0.859375, + 0.2109375 + ], + [ + 0.859375, + 0.203125 + ], + [ + 0.8515625, + 0.1953125 + ], + [ + 0.84375, + 0.1875 + ], + [ + 0.84375, + 0.1796875 + ], + [ + 0.8359375, + 0.171875 + ], + [ + 0.8359375, + 0.1640625 + ], + [ + 0.828125, + 0.15625 + ], + [ + 0.8203125, + 0.1484375 + ], + [ + 0.8203125, + 0.140625 + ], + [ + 0.8125, + 0.1328125 + ], + [ + 0.8125, + 0.125 + ], + [ + 0.8046875, + 0.1171875 + ], + [ + 0.8046875, + 0.109375 + ], + [ + 0.796875, + 0.109375 + ], + [ + 0.7890625, + 0.109375 + ], + [ + 0.78125, + 0.109375 + ], + [ + 0.7734375, + 0.109375 + ], + [ + 0.765625, + 0.109375 + ], + [ + 0.7578125, + 0.109375 + ], + [ + 0.75, + 0.109375 + ], + [ + 0.7421875, + 0.109375 + ], + [ + 0.734375, + 0.109375 + ], + [ + 0.7265625, + 0.109375 + ], + [ + 0.71875, + 0.109375 + ], + [ + 0.7109375, + 0.109375 + ], + [ + 0.703125, + 0.109375 + ], + [ + 0.6953125, + 0.109375 + ], + [ + 0.6875, + 0.109375 + ], + [ + 0.6796875, + 0.109375 + ], + [ + 0.671875, + 0.109375 + ], + [ + 0.6640625, + 0.109375 + ], + [ + 0.65625, + 0.109375 + ], + [ + 0.6484375, + 0.109375 + ], + [ + 0.640625, + 0.109375 + ], + [ + 0.6328125, + 0.109375 + ], + [ + 0.625, + 0.109375 + ], + [ + 0.6171875, + 0.109375 + ], + [ + 0.609375, + 0.1015625 + ], + [ + 0.6015625, + 0.09375 + ], + [ + 0.59375, + 0.0859375 + ], + [ + 0.59375, + 0.078125 + ], + [ + 0.5859375, + 0.0703125 + ], + [ + 0.578125, + 0.0625 + ], + [ + 0.578125, + 0.0546875 + ], + [ + 0.5703125, + 0.046875 + ], + [ + 0.5703125, + 0.0390625 + ], + [ + 0.5625, + 0.03125 + ], + [ + 0.5546875, + 0.0234375 + ], + [ + 0.5546875, + 0.015625 + ], + [ + 0.546875, + 0.0078125 + ], + [ + 0.546875, + 0.0 + ], + [ + 0.5390625, + 0.0 + ], + [ + 0.53125, + 0.0 + ], + [ + 0.5234375, + 0.0 + ], + [ + 0.515625, + 0.0 + ], + [ + 0.5078125, + 0.0 + ], + [ + 0.5, + 0.0 + ], + [ + 0.4921875, + 0.0 + ], + [ + 0.484375, + 0.0 + ], + [ + 0.4765625, + 0.0 + ], + [ + 0.46875, + 0.0 + ], + [ + 0.4609375, + 0.0 + ], + [ + 0.453125, + 0.0 + ], + [ + 0.4453125, + 0.0 + ], + [ + 0.4375, + 0.0 + ], + [ + 0.4296875, + 0.0 + ], + [ + 0.421875, + 0.0 + ], + [ + 0.4140625, + 0.0 + ], + [ + 0.40625, + 0.0 + ], + [ + 0.3984375, + 0.0 + ], + [ + 0.390625, + 0.0 + ], + [ + 0.3828125, + 0.0 + ], + [ + 0.375, + 0.0 + ], + [ + 0.3671875, + 0.0 + ], + [ + 0.359375, + 0.0 + ], + [ + 0.3515625, + 0.0 + ], + [ + 0.34375, + 0.0 + ], + [ + 0.3359375, + 0.0 + ], + [ + 0.328125, + 0.0 + ], + [ + 0.3203125, + 0.0 + ], + [ + 0.3125, + 0.0 + ], + [ + 0.3046875, + 0.0 + ], + [ + 0.296875, + 0.0 + ], + [ + 0.2890625, + 0.0 + ], + [ + 0.28125, + 0.0 + ], + [ + 0.2734375, + 0.0 + ], + [ + 0.265625, + 0.0 + ], + [ + 0.2578125, + 0.0 + ], + [ + 0.25, + 0.0 + ], + [ + 0.2421875, + 0.0 + ], + [ + 0.234375, + 0.0 + ], + [ + 0.2265625, + 0.0 + ], + [ + 0.21875, + 0.0 + ], + [ + 0.2109375, + 0.0 + ], + [ + 0.203125, + 0.0 + ], + [ + 0.1953125, + 0.0 + ], + [ + 0.1875, + 0.0 + ] + ] + ], + "10": [ + [ + [ + 0.1875, + 0.2734375 + ], + [ + 0.1875, + 0.28125 + ], + [ + 0.1796875, + 0.2890625 + ], + [ + 0.1796875, + 0.296875 + ], + [ + 0.171875, + 0.3046875 + ], + [ + 0.171875, + 0.3125 + ], + [ + 0.1640625, + 0.3203125 + ], + [ + 0.15625, + 0.328125 + ], + [ + 0.15625, + 0.3359375 + ], + [ + 0.1484375, + 0.34375 + ], + [ + 0.1484375, + 0.3515625 + ], + [ + 0.140625, + 0.359375 + ], + [ + 0.1328125, + 0.3671875 + ], + [ + 0.1328125, + 0.375 + ], + [ + 0.125, + 0.3828125 + ], + [ + 0.125, + 0.390625 + ], + [ + 0.1171875, + 0.3984375 + ], + [ + 0.109375, + 0.40625 + ], + [ + 0.109375, + 0.4140625 + ], + [ + 0.1015625, + 0.421875 + ], + [ + 0.1015625, + 0.4296875 + ], + [ + 0.09375, + 0.4375 + ], + [ + 0.0859375, + 0.4453125 + ], + [ + 0.0859375, + 0.453125 + ], + [ + 0.078125, + 0.4609375 + ], + [ + 0.078125, + 0.46875 + ], + [ + 0.0703125, + 0.4765625 + ], + [ + 0.0625, + 0.484375 + ], + [ + 0.0625, + 0.4921875 + ], + [ + 0.0546875, + 0.5 + ], + [ + 0.0546875, + 0.5078125 + ], + [ + 0.046875, + 0.515625 + ], + [ + 0.046875, + 0.5234375 + ], + [ + 0.046875, + 0.53125 + ], + [ + 0.0546875, + 0.5390625 + ], + [ + 0.0546875, + 0.546875 + ], + [ + 0.0625, + 0.5546875 + ], + [ + 0.0625, + 0.5625 + ], + [ + 0.0703125, + 0.5703125 + ], + [ + 0.078125, + 0.578125 + ], + [ + 0.078125, + 0.5859375 + ], + [ + 0.0859375, + 0.59375 + ], + [ + 0.0859375, + 0.6015625 + ], + [ + 0.09375, + 0.609375 + ], + [ + 0.09375, + 0.6171875 + ], + [ + 0.1015625, + 0.625 + ], + [ + 0.109375, + 0.6328125 + ], + [ + 0.109375, + 0.640625 + ], + [ + 0.1171875, + 0.6484375 + ], + [ + 0.1171875, + 0.65625 + ], + [ + 0.125, + 0.6640625 + ], + [ + 0.125, + 0.671875 + ], + [ + 0.1328125, + 0.6796875 + ], + [ + 0.140625, + 0.6875 + ], + [ + 0.140625, + 0.6953125 + ], + [ + 0.1484375, + 0.703125 + ], + [ + 0.1484375, + 0.7109375 + ], + [ + 0.15625, + 0.71875 + ], + [ + 0.15625, + 0.7265625 + ], + [ + 0.1640625, + 0.734375 + ], + [ + 0.171875, + 0.7421875 + ], + [ + 0.171875, + 0.75 + ], + [ + 0.1796875, + 0.7578125 + ], + [ + 0.1796875, + 0.765625 + ], + [ + 0.1875, + 0.7734375 + ], + [ + 0.1953125, + 0.7734375 + ], + [ + 0.203125, + 0.7734375 + ], + [ + 0.2109375, + 0.7734375 + ], + [ + 0.21875, + 0.7734375 + ], + [ + 0.2265625, + 0.7734375 + ], + [ + 0.234375, + 0.7734375 + ], + [ + 0.2421875, + 0.7734375 + ], + [ + 0.25, + 0.7734375 + ], + [ + 0.2578125, + 0.7734375 + ], + [ + 0.265625, + 0.7734375 + ], + [ + 0.2734375, + 0.7734375 + ], + [ + 0.28125, + 0.7734375 + ], + [ + 0.2890625, + 0.7734375 + ], + [ + 0.296875, + 0.7734375 + ], + [ + 0.3046875, + 0.7734375 + ], + [ + 0.3125, + 0.7734375 + ], + [ + 0.3203125, + 0.7734375 + ], + [ + 0.328125, + 0.7734375 + ], + [ + 0.3359375, + 0.7734375 + ], + [ + 0.34375, + 0.7734375 + ], + [ + 0.3515625, + 0.7734375 + ], + [ + 0.359375, + 0.7734375 + ], + [ + 0.3671875, + 0.7734375 + ], + [ + 0.375, + 0.7734375 + ], + [ + 0.3828125, + 0.7734375 + ], + [ + 0.390625, + 0.7734375 + ], + [ + 0.3984375, + 0.7734375 + ], + [ + 0.40625, + 0.7734375 + ], + [ + 0.4140625, + 0.7734375 + ], + [ + 0.421875, + 0.7734375 + ], + [ + 0.4296875, + 0.7734375 + ], + [ + 0.4375, + 0.7734375 + ], + [ + 0.4453125, + 0.7734375 + ], + [ + 0.453125, + 0.7734375 + ], + [ + 0.4609375, + 0.7734375 + ], + [ + 0.46875, + 0.7734375 + ], + [ + 0.4765625, + 0.7734375 + ], + [ + 0.484375, + 0.7734375 + ], + [ + 0.4921875, + 0.7734375 + ], + [ + 0.5, + 0.765625 + ], + [ + 0.5, + 0.7578125 + ], + [ + 0.5078125, + 0.75 + ], + [ + 0.515625, + 0.7421875 + ], + [ + 0.515625, + 0.734375 + ], + [ + 0.5234375, + 0.7265625 + ], + [ + 0.5234375, + 0.71875 + ], + [ + 0.53125, + 0.7109375 + ], + [ + 0.5390625, + 0.703125 + ], + [ + 0.5390625, + 0.6953125 + ], + [ + 0.546875, + 0.6875 + ], + [ + 0.546875, + 0.6796875 + ], + [ + 0.5546875, + 0.671875 + ], + [ + 0.5625, + 0.6640625 + ], + [ + 0.5625, + 0.65625 + ], + [ + 0.5703125, + 0.6484375 + ], + [ + 0.5703125, + 0.640625 + ], + [ + 0.578125, + 0.6328125 + ], + [ + 0.5859375, + 0.625 + ], + [ + 0.5859375, + 0.6171875 + ], + [ + 0.59375, + 0.609375 + ], + [ + 0.59375, + 0.6015625 + ], + [ + 0.6015625, + 0.59375 + ], + [ + 0.609375, + 0.5859375 + ], + [ + 0.609375, + 0.578125 + ], + [ + 0.6171875, + 0.5703125 + ], + [ + 0.6171875, + 0.5625 + ], + [ + 0.625, + 0.5546875 + ], + [ + 0.6328125, + 0.546875 + ], + [ + 0.6328125, + 0.5390625 + ], + [ + 0.640625, + 0.53125 + ], + [ + 0.640625, + 0.5234375 + ], + [ + 0.640625, + 0.515625 + ], + [ + 0.6328125, + 0.5078125 + ], + [ + 0.6328125, + 0.5 + ], + [ + 0.625, + 0.4921875 + ], + [ + 0.6171875, + 0.484375 + ], + [ + 0.6171875, + 0.4765625 + ], + [ + 0.6171875, + 0.46875 + ], + [ + 0.6171875, + 0.4609375 + ], + [ + 0.6171875, + 0.453125 + ], + [ + 0.609375, + 0.4453125 + ], + [ + 0.609375, + 0.4375 + ], + [ + 0.6015625, + 0.4296875 + ], + [ + 0.59375, + 0.421875 + ], + [ + 0.59375, + 0.4140625 + ], + [ + 0.5859375, + 0.40625 + ], + [ + 0.5859375, + 0.3984375 + ], + [ + 0.578125, + 0.390625 + ], + [ + 0.5703125, + 0.3828125 + ], + [ + 0.5703125, + 0.375 + ], + [ + 0.5625, + 0.3671875 + ], + [ + 0.5546875, + 0.359375 + ], + [ + 0.5546875, + 0.3515625 + ], + [ + 0.546875, + 0.34375 + ], + [ + 0.546875, + 0.3359375 + ], + [ + 0.5390625, + 0.328125 + ], + [ + 0.53125, + 0.3203125 + ], + [ + 0.53125, + 0.3125 + ], + [ + 0.5234375, + 0.3046875 + ], + [ + 0.515625, + 0.296875 + ], + [ + 0.515625, + 0.2890625 + ], + [ + 0.5078125, + 0.28125 + ], + [ + 0.5078125, + 0.2734375 + ], + [ + 0.5, + 0.2734375 + ], + [ + 0.4921875, + 0.2734375 + ], + [ + 0.484375, + 0.2734375 + ], + [ + 0.4765625, + 0.2734375 + ], + [ + 0.46875, + 0.2734375 + ], + [ + 0.4609375, + 0.2734375 + ], + [ + 0.453125, + 0.2734375 + ], + [ + 0.4453125, + 0.2734375 + ], + [ + 0.4375, + 0.2734375 + ], + [ + 0.4296875, + 0.2734375 + ], + [ + 0.421875, + 0.2734375 + ], + [ + 0.4140625, + 0.2734375 + ], + [ + 0.40625, + 0.2734375 + ], + [ + 0.3984375, + 0.2734375 + ], + [ + 0.390625, + 0.2734375 + ], + [ + 0.3828125, + 0.2734375 + ], + [ + 0.375, + 0.2734375 + ], + [ + 0.3671875, + 0.2734375 + ], + [ + 0.359375, + 0.2734375 + ], + [ + 0.3515625, + 0.2734375 + ], + [ + 0.34375, + 0.2734375 + ], + [ + 0.3359375, + 0.2734375 + ], + [ + 0.328125, + 0.2734375 + ], + [ + 0.3203125, + 0.2734375 + ], + [ + 0.3125, + 0.2734375 + ], + [ + 0.3046875, + 0.2734375 + ], + [ + 0.296875, + 0.2734375 + ], + [ + 0.2890625, + 0.2734375 + ], + [ + 0.28125, + 0.2734375 + ], + [ + 0.2734375, + 0.2734375 + ], + [ + 0.265625, + 0.2734375 + ], + [ + 0.2578125, + 0.2734375 + ], + [ + 0.25, + 0.2734375 + ], + [ + 0.2421875, + 0.2734375 + ], + [ + 0.234375, + 0.2734375 + ], + [ + 0.2265625, + 0.2734375 + ], + [ + 0.21875, + 0.2734375 + ], + [ + 0.2109375, + 0.2734375 + ], + [ + 0.203125, + 0.2734375 + ], + [ + 0.1953125, + 0.2734375 + ] + ], + [ + [ + 0.7578125, + 0.21875 + ], + [ + 0.7578125, + 0.2265625 + ], + [ + 0.75, + 0.234375 + ], + [ + 0.75, + 0.2421875 + ], + [ + 0.7421875, + 0.25 + ], + [ + 0.734375, + 0.2578125 + ], + [ + 0.734375, + 0.265625 + ], + [ + 0.7265625, + 0.2734375 + ], + [ + 0.7265625, + 0.28125 + ], + [ + 0.71875, + 0.2890625 + ], + [ + 0.7109375, + 0.296875 + ], + [ + 0.7109375, + 0.3046875 + ], + [ + 0.703125, + 0.3125 + ], + [ + 0.703125, + 0.3203125 + ], + [ + 0.703125, + 0.328125 + ], + [ + 0.7109375, + 0.3359375 + ], + [ + 0.7109375, + 0.34375 + ], + [ + 0.71875, + 0.3515625 + ], + [ + 0.71875, + 0.359375 + ], + [ + 0.7265625, + 0.3671875 + ], + [ + 0.734375, + 0.375 + ], + [ + 0.734375, + 0.3828125 + ], + [ + 0.7421875, + 0.390625 + ], + [ + 0.7421875, + 0.3984375 + ], + [ + 0.75, + 0.40625 + ], + [ + 0.75, + 0.4140625 + ], + [ + 0.7578125, + 0.421875 + ], + [ + 0.765625, + 0.421875 + ], + [ + 0.7734375, + 0.421875 + ], + [ + 0.78125, + 0.421875 + ], + [ + 0.7890625, + 0.421875 + ], + [ + 0.796875, + 0.421875 + ], + [ + 0.8046875, + 0.421875 + ], + [ + 0.8125, + 0.421875 + ], + [ + 0.8203125, + 0.421875 + ], + [ + 0.828125, + 0.421875 + ], + [ + 0.8359375, + 0.421875 + ], + [ + 0.84375, + 0.421875 + ], + [ + 0.8515625, + 0.421875 + ], + [ + 0.859375, + 0.421875 + ], + [ + 0.8671875, + 0.421875 + ], + [ + 0.875, + 0.421875 + ], + [ + 0.8828125, + 0.421875 + ], + [ + 0.890625, + 0.421875 + ], + [ + 0.8984375, + 0.4140625 + ], + [ + 0.8984375, + 0.40625 + ], + [ + 0.90625, + 0.3984375 + ], + [ + 0.9140625, + 0.390625 + ], + [ + 0.9140625, + 0.3828125 + ], + [ + 0.921875, + 0.375 + ], + [ + 0.9296875, + 0.3671875 + ], + [ + 0.9296875, + 0.359375 + ], + [ + 0.9375, + 0.3515625 + ], + [ + 0.9453125, + 0.34375 + ], + [ + 0.9453125, + 0.3359375 + ], + [ + 0.953125, + 0.328125 + ], + [ + 0.953125, + 0.3203125 + ], + [ + 0.953125, + 0.3125 + ], + [ + 0.9453125, + 0.3046875 + ], + [ + 0.9375, + 0.296875 + ], + [ + 0.9375, + 0.2890625 + ], + [ + 0.9296875, + 0.28125 + ], + [ + 0.921875, + 0.2734375 + ], + [ + 0.921875, + 0.265625 + ], + [ + 0.9140625, + 0.2578125 + ], + [ + 0.90625, + 0.25 + ], + [ + 0.90625, + 0.2421875 + ], + [ + 0.8984375, + 0.234375 + ], + [ + 0.890625, + 0.2265625 + ], + [ + 0.890625, + 0.21875 + ], + [ + 0.8828125, + 0.21875 + ], + [ + 0.875, + 0.21875 + ], + [ + 0.8671875, + 0.21875 + ], + [ + 0.859375, + 0.21875 + ], + [ + 0.8515625, + 0.21875 + ], + [ + 0.84375, + 0.21875 + ], + [ + 0.8359375, + 0.21875 + ], + [ + 0.828125, + 0.21875 + ], + [ + 0.8203125, + 0.21875 + ], + [ + 0.8125, + 0.21875 + ], + [ + 0.8046875, + 0.21875 + ], + [ + 0.796875, + 0.21875 + ], + [ + 0.7890625, + 0.21875 + ], + [ + 0.78125, + 0.21875 + ], + [ + 0.7734375, + 0.21875 + ], + [ + 0.765625, + 0.21875 + ] + ] + ], + "11": [ + [ + [ + 0.375, + 0.0 + ], + [ + 0.375, + 0.0078125 + ], + [ + 0.3671875, + 0.015625 + ], + [ + 0.3671875, + 0.0234375 + ], + [ + 0.359375, + 0.03125 + ], + [ + 0.3515625, + 0.0390625 + ], + [ + 0.3515625, + 0.046875 + ], + [ + 0.34375, + 0.0546875 + ], + [ + 0.34375, + 0.0625 + ], + [ + 0.3359375, + 0.0703125 + ], + [ + 0.328125, + 0.078125 + ], + [ + 0.328125, + 0.0859375 + ], + [ + 0.3203125, + 0.09375 + ], + [ + 0.3203125, + 0.1015625 + ], + [ + 0.3125, + 0.109375 + ], + [ + 0.3046875, + 0.1171875 + ], + [ + 0.3046875, + 0.125 + ], + [ + 0.296875, + 0.1328125 + ], + [ + 0.296875, + 0.140625 + ], + [ + 0.2890625, + 0.1484375 + ], + [ + 0.2890625, + 0.15625 + ], + [ + 0.2890625, + 0.1640625 + ], + [ + 0.296875, + 0.171875 + ], + [ + 0.296875, + 0.1796875 + ], + [ + 0.3046875, + 0.1875 + ], + [ + 0.3046875, + 0.1953125 + ], + [ + 0.3125, + 0.203125 + ], + [ + 0.3203125, + 0.2109375 + ], + [ + 0.3203125, + 0.21875 + ], + [ + 0.328125, + 0.2265625 + ], + [ + 0.328125, + 0.234375 + ], + [ + 0.3359375, + 0.2421875 + ], + [ + 0.3359375, + 0.25 + ], + [ + 0.34375, + 0.2578125 + ], + [ + 0.3515625, + 0.265625 + ], + [ + 0.34375, + 0.2734375 + ], + [ + 0.3359375, + 0.2734375 + ], + [ + 0.328125, + 0.2734375 + ], + [ + 0.3203125, + 0.2734375 + ], + [ + 0.3125, + 0.2734375 + ], + [ + 0.3046875, + 0.2734375 + ], + [ + 0.296875, + 0.2734375 + ], + [ + 0.2890625, + 0.2734375 + ], + [ + 0.28125, + 0.2734375 + ], + [ + 0.2734375, + 0.2734375 + ], + [ + 0.265625, + 0.2734375 + ], + [ + 0.2578125, + 0.2734375 + ], + [ + 0.25, + 0.2734375 + ], + [ + 0.2421875, + 0.2734375 + ], + [ + 0.234375, + 0.2734375 + ], + [ + 0.2265625, + 0.2734375 + ], + [ + 0.21875, + 0.2734375 + ], + [ + 0.2109375, + 0.2734375 + ], + [ + 0.203125, + 0.2734375 + ], + [ + 0.1953125, + 0.2734375 + ], + [ + 0.1875, + 0.2734375 + ], + [ + 0.1796875, + 0.2734375 + ], + [ + 0.1796875, + 0.28125 + ], + [ + 0.171875, + 0.2890625 + ], + [ + 0.171875, + 0.296875 + ], + [ + 0.1640625, + 0.3046875 + ], + [ + 0.1640625, + 0.3125 + ], + [ + 0.15625, + 0.3203125 + ], + [ + 0.1484375, + 0.328125 + ], + [ + 0.1484375, + 0.3359375 + ], + [ + 0.140625, + 0.34375 + ], + [ + 0.140625, + 0.3515625 + ], + [ + 0.1328125, + 0.359375 + ], + [ + 0.125, + 0.3671875 + ], + [ + 0.125, + 0.375 + ], + [ + 0.1171875, + 0.3828125 + ], + [ + 0.1171875, + 0.390625 + ], + [ + 0.109375, + 0.3984375 + ], + [ + 0.1015625, + 0.40625 + ], + [ + 0.1015625, + 0.4140625 + ], + [ + 0.09375, + 0.421875 + ], + [ + 0.09375, + 0.4296875 + ], + [ + 0.0859375, + 0.4375 + ], + [ + 0.0859375, + 0.4453125 + ], + [ + 0.078125, + 0.453125 + ], + [ + 0.0703125, + 0.4609375 + ], + [ + 0.0703125, + 0.46875 + ], + [ + 0.0625, + 0.4765625 + ], + [ + 0.0625, + 0.484375 + ], + [ + 0.0546875, + 0.4921875 + ], + [ + 0.046875, + 0.5 + ], + [ + 0.046875, + 0.5078125 + ], + [ + 0.0390625, + 0.515625 + ], + [ + 0.0390625, + 0.5234375 + ], + [ + 0.03125, + 0.53125 + ], + [ + 0.0234375, + 0.5390625 + ], + [ + 0.0234375, + 0.546875 + ], + [ + 0.015625, + 0.5546875 + ], + [ + 0.015625, + 0.5625 + ], + [ + 0.0078125, + 0.5703125 + ], + [ + 0.0078125, + 0.578125 + ], + [ + 0.0078125, + 0.5859375 + ], + [ + 0.015625, + 0.59375 + ], + [ + 0.015625, + 0.6015625 + ], + [ + 0.0234375, + 0.609375 + ], + [ + 0.0234375, + 0.6171875 + ], + [ + 0.03125, + 0.625 + ], + [ + 0.0390625, + 0.6328125 + ], + [ + 0.0390625, + 0.640625 + ], + [ + 0.046875, + 0.6484375 + ], + [ + 0.046875, + 0.65625 + ], + [ + 0.0546875, + 0.6640625 + ], + [ + 0.0546875, + 0.671875 + ], + [ + 0.0625, + 0.6796875 + ], + [ + 0.0703125, + 0.6875 + ], + [ + 0.0703125, + 0.6953125 + ], + [ + 0.078125, + 0.703125 + ], + [ + 0.078125, + 0.7109375 + ], + [ + 0.0859375, + 0.71875 + ], + [ + 0.0859375, + 0.7265625 + ], + [ + 0.09375, + 0.734375 + ], + [ + 0.1015625, + 0.7421875 + ], + [ + 0.1015625, + 0.75 + ], + [ + 0.109375, + 0.7578125 + ], + [ + 0.109375, + 0.765625 + ], + [ + 0.1171875, + 0.7734375 + ], + [ + 0.1171875, + 0.78125 + ], + [ + 0.125, + 0.7890625 + ], + [ + 0.1328125, + 0.796875 + ], + [ + 0.1328125, + 0.8046875 + ], + [ + 0.140625, + 0.8125 + ], + [ + 0.140625, + 0.8203125 + ], + [ + 0.1484375, + 0.828125 + ], + [ + 0.1484375, + 0.8359375 + ], + [ + 0.15625, + 0.84375 + ], + [ + 0.1640625, + 0.8515625 + ], + [ + 0.1640625, + 0.859375 + ], + [ + 0.171875, + 0.8671875 + ], + [ + 0.171875, + 0.875 + ], + [ + 0.1796875, + 0.8828125 + ], + [ + 0.1875, + 0.8828125 + ], + [ + 0.1953125, + 0.8828125 + ], + [ + 0.203125, + 0.8828125 + ], + [ + 0.2109375, + 0.8828125 + ], + [ + 0.21875, + 0.8828125 + ], + [ + 0.2265625, + 0.8828125 + ], + [ + 0.234375, + 0.8828125 + ], + [ + 0.2421875, + 0.8828125 + ], + [ + 0.25, + 0.8828125 + ], + [ + 0.2578125, + 0.8828125 + ], + [ + 0.265625, + 0.8828125 + ], + [ + 0.2734375, + 0.8828125 + ], + [ + 0.28125, + 0.8828125 + ], + [ + 0.2890625, + 0.8828125 + ], + [ + 0.296875, + 0.8828125 + ], + [ + 0.3046875, + 0.8828125 + ], + [ + 0.3125, + 0.8828125 + ], + [ + 0.3203125, + 0.8828125 + ], + [ + 0.328125, + 0.8828125 + ], + [ + 0.3359375, + 0.8828125 + ], + [ + 0.34375, + 0.8828125 + ], + [ + 0.3515625, + 0.8828125 + ], + [ + 0.359375, + 0.8828125 + ], + [ + 0.3671875, + 0.8828125 + ], + [ + 0.375, + 0.8828125 + ], + [ + 0.3828125, + 0.8828125 + ], + [ + 0.390625, + 0.8828125 + ], + [ + 0.3984375, + 0.8828125 + ], + [ + 0.40625, + 0.8828125 + ], + [ + 0.4140625, + 0.8828125 + ], + [ + 0.421875, + 0.8828125 + ], + [ + 0.4296875, + 0.8828125 + ], + [ + 0.4375, + 0.8828125 + ], + [ + 0.4453125, + 0.8828125 + ], + [ + 0.453125, + 0.8828125 + ], + [ + 0.4609375, + 0.8828125 + ], + [ + 0.46875, + 0.8828125 + ], + [ + 0.4765625, + 0.8828125 + ], + [ + 0.484375, + 0.8828125 + ], + [ + 0.4921875, + 0.8828125 + ], + [ + 0.5, + 0.8828125 + ], + [ + 0.5078125, + 0.8828125 + ], + [ + 0.515625, + 0.8828125 + ], + [ + 0.5234375, + 0.8828125 + ], + [ + 0.53125, + 0.8828125 + ], + [ + 0.5390625, + 0.8828125 + ], + [ + 0.546875, + 0.875 + ], + [ + 0.546875, + 0.8671875 + ], + [ + 0.5546875, + 0.859375 + ], + [ + 0.5546875, + 0.8515625 + ], + [ + 0.5625, + 0.84375 + ], + [ + 0.5703125, + 0.8359375 + ], + [ + 0.5703125, + 0.828125 + ], + [ + 0.578125, + 0.8203125 + ], + [ + 0.5859375, + 0.8203125 + ], + [ + 0.59375, + 0.8203125 + ], + [ + 0.6015625, + 0.8203125 + ], + [ + 0.609375, + 0.8203125 + ], + [ + 0.6171875, + 0.8203125 + ], + [ + 0.625, + 0.8203125 + ], + [ + 0.6328125, + 0.8203125 + ], + [ + 0.640625, + 0.8203125 + ], + [ + 0.6484375, + 0.8203125 + ], + [ + 0.65625, + 0.8203125 + ], + [ + 0.6640625, + 0.8203125 + ], + [ + 0.671875, + 0.8203125 + ], + [ + 0.6796875, + 0.8203125 + ], + [ + 0.6875, + 0.8203125 + ], + [ + 0.6953125, + 0.8203125 + ], + [ + 0.703125, + 0.8203125 + ], + [ + 0.7109375, + 0.8125 + ], + [ + 0.7109375, + 0.8046875 + ], + [ + 0.71875, + 0.796875 + ], + [ + 0.71875, + 0.7890625 + ], + [ + 0.7265625, + 0.78125 + ], + [ + 0.734375, + 0.7734375 + ], + [ + 0.734375, + 0.765625 + ], + [ + 0.7421875, + 0.7578125 + ], + [ + 0.7421875, + 0.75 + ], + [ + 0.75, + 0.7421875 + ], + [ + 0.75, + 0.734375 + ], + [ + 0.7578125, + 0.7265625 + ], + [ + 0.765625, + 0.71875 + ], + [ + 0.765625, + 0.7109375 + ], + [ + 0.7734375, + 0.703125 + ], + [ + 0.7734375, + 0.6953125 + ], + [ + 0.78125, + 0.6875 + ], + [ + 0.78125, + 0.6796875 + ], + [ + 0.78125, + 0.671875 + ], + [ + 0.7734375, + 0.6640625 + ], + [ + 0.7734375, + 0.65625 + ], + [ + 0.765625, + 0.6484375 + ], + [ + 0.765625, + 0.640625 + ], + [ + 0.7578125, + 0.6328125 + ], + [ + 0.75, + 0.625 + ], + [ + 0.75, + 0.6171875 + ], + [ + 0.7421875, + 0.609375 + ], + [ + 0.7421875, + 0.6015625 + ], + [ + 0.734375, + 0.59375 + ], + [ + 0.734375, + 0.5859375 + ], + [ + 0.7265625, + 0.578125 + ], + [ + 0.71875, + 0.5703125 + ], + [ + 0.71875, + 0.5625 + ], + [ + 0.7109375, + 0.5546875 + ], + [ + 0.7109375, + 0.546875 + ], + [ + 0.703125, + 0.5390625 + ], + [ + 0.703125, + 0.53125 + ], + [ + 0.6953125, + 0.53125 + ], + [ + 0.6875, + 0.53125 + ], + [ + 0.6796875, + 0.5234375 + ], + [ + 0.6796875, + 0.515625 + ], + [ + 0.671875, + 0.5078125 + ], + [ + 0.671875, + 0.5 + ], + [ + 0.6640625, + 0.4921875 + ], + [ + 0.65625, + 0.484375 + ], + [ + 0.65625, + 0.4765625 + ], + [ + 0.6484375, + 0.46875 + ], + [ + 0.6484375, + 0.4609375 + ], + [ + 0.640625, + 0.453125 + ], + [ + 0.6328125, + 0.4453125 + ], + [ + 0.6328125, + 0.4375 + ], + [ + 0.625, + 0.4296875 + ], + [ + 0.625, + 0.421875 + ], + [ + 0.6171875, + 0.4140625 + ], + [ + 0.6171875, + 0.40625 + ], + [ + 0.609375, + 0.3984375 + ], + [ + 0.6015625, + 0.390625 + ], + [ + 0.6015625, + 0.3828125 + ], + [ + 0.59375, + 0.375 + ], + [ + 0.59375, + 0.3671875 + ], + [ + 0.5859375, + 0.359375 + ], + [ + 0.578125, + 0.3515625 + ], + [ + 0.578125, + 0.34375 + ], + [ + 0.5703125, + 0.3359375 + ], + [ + 0.5703125, + 0.328125 + ], + [ + 0.5625, + 0.3203125 + ], + [ + 0.5625, + 0.3125 + ], + [ + 0.5703125, + 0.3046875 + ], + [ + 0.5703125, + 0.296875 + ], + [ + 0.578125, + 0.2890625 + ], + [ + 0.578125, + 0.28125 + ], + [ + 0.5859375, + 0.2734375 + ], + [ + 0.5859375, + 0.265625 + ], + [ + 0.59375, + 0.2578125 + ], + [ + 0.6015625, + 0.25 + ], + [ + 0.6015625, + 0.2421875 + ], + [ + 0.609375, + 0.234375 + ], + [ + 0.609375, + 0.2265625 + ], + [ + 0.6171875, + 0.21875 + ], + [ + 0.6171875, + 0.2109375 + ], + [ + 0.625, + 0.203125 + ], + [ + 0.6328125, + 0.1953125 + ], + [ + 0.6328125, + 0.1875 + ], + [ + 0.640625, + 0.1796875 + ], + [ + 0.640625, + 0.171875 + ], + [ + 0.6484375, + 0.1640625 + ], + [ + 0.6484375, + 0.15625 + ], + [ + 0.6484375, + 0.1484375 + ], + [ + 0.640625, + 0.140625 + ], + [ + 0.640625, + 0.1328125 + ], + [ + 0.6328125, + 0.125 + ], + [ + 0.6328125, + 0.1171875 + ], + [ + 0.625, + 0.109375 + ], + [ + 0.6171875, + 0.1015625 + ], + [ + 0.6171875, + 0.09375 + ], + [ + 0.609375, + 0.0859375 + ], + [ + 0.609375, + 0.078125 + ], + [ + 0.6015625, + 0.0703125 + ], + [ + 0.59375, + 0.0625 + ], + [ + 0.59375, + 0.0546875 + ], + [ + 0.5859375, + 0.046875 + ], + [ + 0.5859375, + 0.0390625 + ], + [ + 0.578125, + 0.03125 + ], + [ + 0.5703125, + 0.0234375 + ], + [ + 0.5703125, + 0.015625 + ], + [ + 0.5625, + 0.0078125 + ], + [ + 0.5625, + 0.0 + ], + [ + 0.5546875, + 0.0 + ], + [ + 0.546875, + 0.0 + ], + [ + 0.5390625, + 0.0 + ], + [ + 0.53125, + 0.0 + ], + [ + 0.5234375, + 0.0 + ], + [ + 0.515625, + 0.0 + ], + [ + 0.5078125, + 0.0 + ], + [ + 0.5, + 0.0 + ], + [ + 0.4921875, + 0.0 + ], + [ + 0.484375, + 0.0 + ], + [ + 0.4765625, + 0.0 + ], + [ + 0.46875, + 0.0 + ], + [ + 0.4609375, + 0.0 + ], + [ + 0.453125, + 0.0 + ], + [ + 0.4453125, + 0.0 + ], + [ + 0.4375, + 0.0 + ], + [ + 0.4296875, + 0.0 + ], + [ + 0.421875, + 0.0 + ], + [ + 0.4140625, + 0.0 + ], + [ + 0.40625, + 0.0 + ], + [ + 0.3984375, + 0.0 + ], + [ + 0.390625, + 0.0 + ], + [ + 0.3828125, + 0.0 + ] + ] + ], + "12": [ + [ + [ + 0.2578125, + 0.8671875 + ], + [ + 0.2578125, + 0.875 + ], + [ + 0.25, + 0.8828125 + ], + [ + 0.2421875, + 0.890625 + ], + [ + 0.2421875, + 0.8984375 + ], + [ + 0.234375, + 0.90625 + ], + [ + 0.234375, + 0.9140625 + ], + [ + 0.234375, + 0.921875 + ], + [ + 0.2421875, + 0.9296875 + ], + [ + 0.2421875, + 0.9375 + ], + [ + 0.25, + 0.9453125 + ], + [ + 0.25, + 0.953125 + ], + [ + 0.2578125, + 0.9609375 + ], + [ + 0.265625, + 0.9609375 + ], + [ + 0.2734375, + 0.9609375 + ], + [ + 0.28125, + 0.9609375 + ], + [ + 0.2890625, + 0.9609375 + ], + [ + 0.296875, + 0.9609375 + ], + [ + 0.3046875, + 0.9609375 + ], + [ + 0.3125, + 0.9609375 + ], + [ + 0.3203125, + 0.9609375 + ], + [ + 0.328125, + 0.953125 + ], + [ + 0.328125, + 0.9453125 + ], + [ + 0.3359375, + 0.9375 + ], + [ + 0.3359375, + 0.9296875 + ], + [ + 0.34375, + 0.921875 + ], + [ + 0.34375, + 0.9140625 + ], + [ + 0.34375, + 0.90625 + ], + [ + 0.3359375, + 0.8984375 + ], + [ + 0.3359375, + 0.890625 + ], + [ + 0.328125, + 0.8828125 + ], + [ + 0.3203125, + 0.875 + ], + [ + 0.3203125, + 0.8671875 + ], + [ + 0.3125, + 0.8671875 + ], + [ + 0.3046875, + 0.8671875 + ], + [ + 0.296875, + 0.8671875 + ], + [ + 0.2890625, + 0.8671875 + ], + [ + 0.28125, + 0.8671875 + ], + [ + 0.2734375, + 0.8671875 + ], + [ + 0.265625, + 0.8671875 + ] + ], + [ + [ + 0.125, + 0.0859375 + ], + [ + 0.125, + 0.09375 + ], + [ + 0.1171875, + 0.1015625 + ], + [ + 0.1171875, + 0.109375 + ], + [ + 0.109375, + 0.1171875 + ], + [ + 0.109375, + 0.125 + ], + [ + 0.1015625, + 0.1328125 + ], + [ + 0.09375, + 0.140625 + ], + [ + 0.09375, + 0.1484375 + ], + [ + 0.0859375, + 0.15625 + ], + [ + 0.0859375, + 0.1640625 + ], + [ + 0.078125, + 0.171875 + ], + [ + 0.0703125, + 0.1796875 + ], + [ + 0.0703125, + 0.1875 + ], + [ + 0.0625, + 0.1953125 + ], + [ + 0.0625, + 0.203125 + ], + [ + 0.0546875, + 0.2109375 + ], + [ + 0.046875, + 0.21875 + ], + [ + 0.046875, + 0.2265625 + ], + [ + 0.0390625, + 0.234375 + ], + [ + 0.0390625, + 0.2421875 + ], + [ + 0.03125, + 0.25 + ], + [ + 0.0234375, + 0.2578125 + ], + [ + 0.0234375, + 0.265625 + ], + [ + 0.015625, + 0.2734375 + ], + [ + 0.015625, + 0.28125 + ], + [ + 0.0078125, + 0.2890625 + ], + [ + 0.0078125, + 0.296875 + ], + [ + 0.0078125, + 0.3046875 + ], + [ + 0.015625, + 0.3125 + ], + [ + 0.015625, + 0.3203125 + ], + [ + 0.0234375, + 0.328125 + ], + [ + 0.0234375, + 0.3359375 + ], + [ + 0.03125, + 0.34375 + ], + [ + 0.0390625, + 0.3515625 + ], + [ + 0.0390625, + 0.359375 + ], + [ + 0.046875, + 0.3671875 + ], + [ + 0.046875, + 0.375 + ], + [ + 0.0546875, + 0.3828125 + ], + [ + 0.0546875, + 0.390625 + ], + [ + 0.0625, + 0.3984375 + ], + [ + 0.0703125, + 0.40625 + ], + [ + 0.0703125, + 0.4140625 + ], + [ + 0.078125, + 0.421875 + ], + [ + 0.078125, + 0.4296875 + ], + [ + 0.0859375, + 0.4375 + ], + [ + 0.0859375, + 0.4453125 + ], + [ + 0.09375, + 0.453125 + ], + [ + 0.1015625, + 0.4609375 + ], + [ + 0.1015625, + 0.46875 + ], + [ + 0.109375, + 0.4765625 + ], + [ + 0.109375, + 0.484375 + ], + [ + 0.1171875, + 0.4921875 + ], + [ + 0.1171875, + 0.5 + ], + [ + 0.125, + 0.5078125 + ], + [ + 0.1328125, + 0.5078125 + ], + [ + 0.140625, + 0.5078125 + ], + [ + 0.1484375, + 0.5078125 + ], + [ + 0.15625, + 0.5078125 + ], + [ + 0.1640625, + 0.5078125 + ], + [ + 0.171875, + 0.5078125 + ], + [ + 0.1796875, + 0.5078125 + ], + [ + 0.1875, + 0.5078125 + ], + [ + 0.1953125, + 0.5078125 + ], + [ + 0.203125, + 0.5078125 + ], + [ + 0.2109375, + 0.5078125 + ], + [ + 0.21875, + 0.5078125 + ], + [ + 0.2265625, + 0.5078125 + ], + [ + 0.234375, + 0.5078125 + ], + [ + 0.2421875, + 0.5078125 + ], + [ + 0.25, + 0.5078125 + ], + [ + 0.2578125, + 0.5078125 + ], + [ + 0.265625, + 0.5078125 + ], + [ + 0.2734375, + 0.5078125 + ], + [ + 0.28125, + 0.5078125 + ], + [ + 0.2890625, + 0.5078125 + ], + [ + 0.296875, + 0.5078125 + ], + [ + 0.3046875, + 0.5078125 + ], + [ + 0.3125, + 0.5078125 + ], + [ + 0.3203125, + 0.5078125 + ], + [ + 0.328125, + 0.5078125 + ], + [ + 0.3359375, + 0.5078125 + ], + [ + 0.34375, + 0.5078125 + ], + [ + 0.3515625, + 0.5078125 + ], + [ + 0.359375, + 0.5078125 + ], + [ + 0.3671875, + 0.5078125 + ], + [ + 0.375, + 0.5078125 + ], + [ + 0.3828125, + 0.5 + ], + [ + 0.3828125, + 0.4921875 + ], + [ + 0.390625, + 0.484375 + ], + [ + 0.390625, + 0.4765625 + ], + [ + 0.3984375, + 0.46875 + ], + [ + 0.3984375, + 0.4609375 + ], + [ + 0.40625, + 0.453125 + ], + [ + 0.4140625, + 0.4453125 + ], + [ + 0.4140625, + 0.4375 + ], + [ + 0.421875, + 0.4296875 + ], + [ + 0.421875, + 0.421875 + ], + [ + 0.4296875, + 0.4140625 + ], + [ + 0.4296875, + 0.40625 + ], + [ + 0.4375, + 0.3984375 + ], + [ + 0.4453125, + 0.390625 + ], + [ + 0.4453125, + 0.3828125 + ], + [ + 0.453125, + 0.375 + ], + [ + 0.453125, + 0.3671875 + ], + [ + 0.4609375, + 0.359375 + ], + [ + 0.4609375, + 0.3515625 + ], + [ + 0.46875, + 0.34375 + ], + [ + 0.4765625, + 0.3359375 + ], + [ + 0.4765625, + 0.328125 + ], + [ + 0.484375, + 0.3203125 + ], + [ + 0.484375, + 0.3125 + ], + [ + 0.4921875, + 0.3046875 + ], + [ + 0.4921875, + 0.296875 + ], + [ + 0.4921875, + 0.2890625 + ], + [ + 0.484375, + 0.28125 + ], + [ + 0.484375, + 0.2734375 + ], + [ + 0.4765625, + 0.265625 + ], + [ + 0.4765625, + 0.2578125 + ], + [ + 0.46875, + 0.25 + ], + [ + 0.4609375, + 0.2421875 + ], + [ + 0.4609375, + 0.234375 + ], + [ + 0.453125, + 0.2265625 + ], + [ + 0.453125, + 0.21875 + ], + [ + 0.4453125, + 0.2109375 + ], + [ + 0.4375, + 0.203125 + ], + [ + 0.4375, + 0.1953125 + ], + [ + 0.4296875, + 0.1875 + ], + [ + 0.4296875, + 0.1796875 + ], + [ + 0.421875, + 0.171875 + ], + [ + 0.4140625, + 0.1640625 + ], + [ + 0.4140625, + 0.15625 + ], + [ + 0.40625, + 0.1484375 + ], + [ + 0.40625, + 0.140625 + ], + [ + 0.3984375, + 0.1328125 + ], + [ + 0.390625, + 0.125 + ], + [ + 0.390625, + 0.1171875 + ], + [ + 0.3828125, + 0.109375 + ], + [ + 0.3828125, + 0.1015625 + ], + [ + 0.375, + 0.09375 + ], + [ + 0.375, + 0.0859375 + ], + [ + 0.3671875, + 0.0859375 + ], + [ + 0.359375, + 0.0859375 + ], + [ + 0.3515625, + 0.0859375 + ], + [ + 0.34375, + 0.0859375 + ], + [ + 0.3359375, + 0.0859375 + ], + [ + 0.328125, + 0.0859375 + ], + [ + 0.3203125, + 0.0859375 + ], + [ + 0.3125, + 0.0859375 + ], + [ + 0.3046875, + 0.0859375 + ], + [ + 0.296875, + 0.0859375 + ], + [ + 0.2890625, + 0.0859375 + ], + [ + 0.28125, + 0.0859375 + ], + [ + 0.2734375, + 0.0859375 + ], + [ + 0.265625, + 0.0859375 + ], + [ + 0.2578125, + 0.0859375 + ], + [ + 0.25, + 0.0859375 + ], + [ + 0.2421875, + 0.0859375 + ], + [ + 0.234375, + 0.0859375 + ], + [ + 0.2265625, + 0.0859375 + ], + [ + 0.21875, + 0.0859375 + ], + [ + 0.2109375, + 0.0859375 + ], + [ + 0.203125, + 0.0859375 + ], + [ + 0.1953125, + 0.0859375 + ], + [ + 0.1875, + 0.0859375 + ], + [ + 0.1796875, + 0.0859375 + ], + [ + 0.171875, + 0.0859375 + ], + [ + 0.1640625, + 0.0859375 + ], + [ + 0.15625, + 0.0859375 + ], + [ + 0.1484375, + 0.0859375 + ], + [ + 0.140625, + 0.0859375 + ], + [ + 0.1328125, + 0.0859375 + ] + ], + [ + [ + 0.6015625, + 0.0234375 + ], + [ + 0.6015625, + 0.03125 + ], + [ + 0.59375, + 0.0390625 + ], + [ + 0.59375, + 0.046875 + ], + [ + 0.5859375, + 0.0546875 + ], + [ + 0.578125, + 0.0625 + ], + [ + 0.578125, + 0.0703125 + ], + [ + 0.5703125, + 0.078125 + ], + [ + 0.5703125, + 0.0859375 + ], + [ + 0.5625, + 0.09375 + ], + [ + 0.5546875, + 0.1015625 + ], + [ + 0.5546875, + 0.109375 + ], + [ + 0.546875, + 0.1171875 + ], + [ + 0.546875, + 0.125 + ], + [ + 0.5390625, + 0.1328125 + ], + [ + 0.53125, + 0.140625 + ], + [ + 0.53125, + 0.1484375 + ], + [ + 0.5234375, + 0.15625 + ], + [ + 0.5234375, + 0.1640625 + ], + [ + 0.515625, + 0.171875 + ], + [ + 0.515625, + 0.1796875 + ], + [ + 0.515625, + 0.1875 + ], + [ + 0.5234375, + 0.1953125 + ], + [ + 0.5234375, + 0.203125 + ], + [ + 0.53125, + 0.2109375 + ], + [ + 0.53125, + 0.21875 + ], + [ + 0.5390625, + 0.2265625 + ], + [ + 0.546875, + 0.234375 + ], + [ + 0.546875, + 0.2421875 + ], + [ + 0.5546875, + 0.25 + ], + [ + 0.5546875, + 0.2578125 + ], + [ + 0.5625, + 0.265625 + ], + [ + 0.5625, + 0.2734375 + ], + [ + 0.5703125, + 0.28125 + ], + [ + 0.578125, + 0.2890625 + ], + [ + 0.578125, + 0.296875 + ], + [ + 0.5859375, + 0.3046875 + ], + [ + 0.5859375, + 0.3125 + ], + [ + 0.59375, + 0.3203125 + ], + [ + 0.59375, + 0.328125 + ], + [ + 0.6015625, + 0.3359375 + ], + [ + 0.609375, + 0.3359375 + ], + [ + 0.6171875, + 0.3359375 + ], + [ + 0.625, + 0.3359375 + ], + [ + 0.6328125, + 0.3359375 + ], + [ + 0.640625, + 0.3359375 + ], + [ + 0.6484375, + 0.3359375 + ], + [ + 0.65625, + 0.3359375 + ], + [ + 0.6640625, + 0.3359375 + ], + [ + 0.671875, + 0.3359375 + ], + [ + 0.6796875, + 0.3359375 + ], + [ + 0.6875, + 0.3359375 + ], + [ + 0.6953125, + 0.3359375 + ], + [ + 0.703125, + 0.3359375 + ], + [ + 0.7109375, + 0.3359375 + ], + [ + 0.71875, + 0.3359375 + ], + [ + 0.7265625, + 0.3359375 + ], + [ + 0.734375, + 0.3359375 + ], + [ + 0.7421875, + 0.3359375 + ], + [ + 0.75, + 0.3359375 + ], + [ + 0.7578125, + 0.3359375 + ], + [ + 0.765625, + 0.3359375 + ], + [ + 0.7734375, + 0.3359375 + ], + [ + 0.78125, + 0.3359375 + ], + [ + 0.7890625, + 0.3359375 + ], + [ + 0.796875, + 0.328125 + ], + [ + 0.796875, + 0.3203125 + ], + [ + 0.8046875, + 0.3125 + ], + [ + 0.8046875, + 0.3046875 + ], + [ + 0.8125, + 0.296875 + ], + [ + 0.8125, + 0.2890625 + ], + [ + 0.8203125, + 0.28125 + ], + [ + 0.828125, + 0.2734375 + ], + [ + 0.828125, + 0.265625 + ], + [ + 0.8359375, + 0.2578125 + ], + [ + 0.8359375, + 0.25 + ], + [ + 0.84375, + 0.2421875 + ], + [ + 0.84375, + 0.234375 + ], + [ + 0.8515625, + 0.2265625 + ], + [ + 0.859375, + 0.21875 + ], + [ + 0.859375, + 0.2109375 + ], + [ + 0.8671875, + 0.203125 + ], + [ + 0.8671875, + 0.1953125 + ], + [ + 0.875, + 0.1875 + ], + [ + 0.875, + 0.1796875 + ], + [ + 0.875, + 0.171875 + ], + [ + 0.8671875, + 0.1640625 + ], + [ + 0.8671875, + 0.15625 + ], + [ + 0.859375, + 0.1484375 + ], + [ + 0.859375, + 0.140625 + ], + [ + 0.8515625, + 0.1328125 + ], + [ + 0.84375, + 0.125 + ], + [ + 0.84375, + 0.1171875 + ], + [ + 0.8359375, + 0.109375 + ], + [ + 0.8359375, + 0.1015625 + ], + [ + 0.828125, + 0.09375 + ], + [ + 0.8203125, + 0.0859375 + ], + [ + 0.8203125, + 0.078125 + ], + [ + 0.8125, + 0.0703125 + ], + [ + 0.8125, + 0.0625 + ], + [ + 0.8046875, + 0.0546875 + ], + [ + 0.796875, + 0.046875 + ], + [ + 0.796875, + 0.0390625 + ], + [ + 0.7890625, + 0.03125 + ], + [ + 0.7890625, + 0.0234375 + ], + [ + 0.78125, + 0.0234375 + ], + [ + 0.7734375, + 0.0234375 + ], + [ + 0.765625, + 0.0234375 + ], + [ + 0.7578125, + 0.0234375 + ], + [ + 0.75, + 0.0234375 + ], + [ + 0.7421875, + 0.0234375 + ], + [ + 0.734375, + 0.0234375 + ], + [ + 0.7265625, + 0.0234375 + ], + [ + 0.71875, + 0.0234375 + ], + [ + 0.7109375, + 0.0234375 + ], + [ + 0.703125, + 0.0234375 + ], + [ + 0.6953125, + 0.0234375 + ], + [ + 0.6875, + 0.0234375 + ], + [ + 0.6796875, + 0.0234375 + ], + [ + 0.671875, + 0.0234375 + ], + [ + 0.6640625, + 0.0234375 + ], + [ + 0.65625, + 0.0234375 + ], + [ + 0.6484375, + 0.0234375 + ], + [ + 0.640625, + 0.0234375 + ], + [ + 0.6328125, + 0.0234375 + ], + [ + 0.625, + 0.0234375 + ], + [ + 0.6171875, + 0.0234375 + ], + [ + 0.609375, + 0.0234375 + ] + ] + ] + } +} \ No newline at end of file diff --git a/external/README.md b/external/README.md index 11d332fd1b2..b64723080b6 100644 --- a/external/README.md +++ b/external/README.md @@ -9,30 +9,41 @@ ID | Name | Complexity (GFlops) | Model size (MB) | Path ote_anomaly_classification_padim | PADIM | 3.9 | 168.4 | anomaly/anomaly_classification/configs/padim/template.yaml ote_anomaly_classification_stfpm | STFPM | 5.6 | 21.1 | anomaly/anomaly_classification/configs/stfpm/template.yaml +## Anomaly Segmentation +ID | Name | Complexity (GFlops) | Model size (MB) | Path +------- | ------- | ------- | ------- | ------- +ote_anomaly_segmentation_padim | PADIM | 3.9 | 168.4 | anomaly/anomaly_segmentation/configs/padim/template.yaml +ote_anomaly_segmentation_stfpm | STFPM | 5.6 | 21.1 | anomaly/anomaly_segmentation/configs/stfpm/template.yaml + ## Image Classification ID | Name | Complexity (GFlops) | Model size (MB) | Path ------- | ------- | ------- | ------- | ------- -MobileNet-V3-large-0.75x | MobileNet-V3-large-0.75x | 0.32 | 2.76 | deep-object-reid/configs/ote_custom_classification/mobilenet_v3_large_075/template.yaml +Custom_Image_Classification_MobileNet-V3-large-1x | MobileNet-V3-large-1x | 0.44 | 4.29 | deep-object-reid/configs/ote_custom_classification/mobilenet_v3_large_1/template.yaml Custom_Image_Classification_EfficinetNet-B0 | EfficientNet-B0 | 0.81 | 4.09 | deep-object-reid/configs/ote_custom_classification/efficientnet_b0/template.yaml +Custom_Image_Classification_EfficientNet-V2-S | EfficientNet-V2-S | 5.76 | 20.23 | deep-object-reid/configs/ote_custom_classification/efficientnet_v2_s/template.yaml ## Object Detection ID | Name | Complexity (GFlops) | Model size (MB) | Path ------- | ------- | ------- | ------- | ------- +Custom_Object_Detection_YOLOX | YOLOX | 6.5 | 20.4 | mmdetection/configs/ote/custom-object-detection/cspdarknet_YOLOX/template.yaml Custom_Object_Detection_Gen3_SSD | SSD | 9.4 | 7.6 | mmdetection/configs/ote/custom-object-detection/gen3_mobilenetV2_SSD/template.yaml Custom_Object_Detection_Gen3_ATSS | ATSS | 20.6 | 9.1 | mmdetection/configs/ote/custom-object-detection/gen3_mobilenetV2_ATSS/template.yaml -Custom_Object_Detection_Gen3_VFNet | VFNet | 457.4 | 126.0 | mmdetection/configs/ote/custom-object-detection/gen3_resnet50_VFNet/template.yaml ## Object Counting ID | Name | Complexity (GFlops) | Model size (MB) | Path ------- | ------- | ------- | ------- | ------- +Custom_Counting_Instance_Segmentation_MaskRCNN_EfficientNetB2B | MaskRCNN-EfficientNetB2B | 68.48 | 13.27 | mmdetection/configs/ote/custom-counting-instance-seg/efficientnetb2b_maskrcnn/template.yaml Custom_Counting_Instance_Segmentation_MaskRCNN_ResNet50 | MaskRCNN-ResNet50 | 533.8 | 177.9 | mmdetection/configs/ote/custom-counting-instance-seg/resnet50_maskrcnn/template.yaml ## Rotated Object Detection ID | Name | Complexity (GFlops) | Model size (MB) | Path ------- | ------- | ------- | ------- | ------- +Custom_Rotated_Detection_via_Instance_Segmentation_MaskRCNN_EfficientNetB2B | MaskRCNN-EfficientNetB2B | 68.48 | 13.27 | mmdetection/configs/ote/rotated_detection/efficientnetb2b_maskrcnn/template.yaml Custom_Rotated_Detection_via_Instance_Segmentation_MaskRCNN_ResNet50 | MaskRCNN-ResNet50 | 533.8 | 177.9 | mmdetection/configs/ote/rotated_detection/resnet50_maskrcnn/template.yaml ## Semantic Segmentaion ID | Name | Complexity (GFlops) | Model size (MB) | Path ------- | ------- | ------- | ------- | ------- Custom_Semantic_Segmentation_Lite-HRNet-18_OCR | Lite-HRNet-18 OCR | 3.45 | 4.5 | mmsegmentation/configs/ote/custom-sematic-segmentation/ocr-lite-hrnet-18/template.yaml +Custom_Semantic_Segmentation_Lite-HRNet-18-mod2_OCR | Lite-HRNet-18-mod2 OCR | 3.63 | 4.8 | mmsegmentation/configs/ote/custom-sematic-segmentation/ocr-lite-hrnet-18-mod2/template.yaml +Custom_Semantic_Segmentation_Lite-HRNet-x-mod3_OCR | Lite-HRNet-x-mod3 OCR | 13.97 | 6.4 | mmsegmentation/configs/ote/custom-sematic-segmentation/ocr-lite-hrnet-x-mod3/template.yaml diff --git a/external/anomaly/anomaly_classification/__init__.py b/external/anomaly/anomaly_classification/__init__.py index 24d5d56a038..9db5f0d8b62 100644 --- a/external/anomaly/anomaly_classification/__init__.py +++ b/external/anomaly/anomaly_classification/__init__.py @@ -15,8 +15,3 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions # and limitations under the License. - -from .openvino import OpenVINOAnomalyClassificationTask -from .task import AnomalyClassificationTask - -__all__ = ["AnomalyClassificationTask", "OpenVINOAnomalyClassificationTask"] diff --git a/external/anomaly/anomaly_classification/configs/padim/__init__.py b/external/anomaly/anomaly_classification/configs/padim/__init__.py index 36a4487d1bc..6536c75c39d 100644 --- a/external/anomaly/anomaly_classification/configs/padim/__init__.py +++ b/external/anomaly/anomaly_classification/configs/padim/__init__.py @@ -17,6 +17,6 @@ # See the License for the specific language governing permissions # and limitations under the License. -from .configuration import PadimConfig +from .configuration import PadimAnomalyClassificationConfig -__all__ = ["PadimConfig"] +__all__ = ["PadimAnomalyClassificationConfig"] diff --git a/external/anomaly/anomaly_classification/configs/padim/configuration.py b/external/anomaly/anomaly_classification/configs/padim/configuration.py index 366ac437e02..69b1588ab30 100644 --- a/external/anomaly/anomaly_classification/configs/padim/configuration.py +++ b/external/anomaly/anomaly_classification/configs/padim/configuration.py @@ -16,13 +16,13 @@ # See the License for the specific language governing permissions # and limitations under the License. -from anomaly_classification.configs.configuration import BaseAnomalyClassificationConfig from attr import attrs +from ote_anomalib.configs.configuration import BaseAnomalyConfig from ote_sdk.configuration.elements import string_attribute @attrs -class PadimConfig(BaseAnomalyClassificationConfig): +class PadimAnomalyClassificationConfig(BaseAnomalyConfig): """ Configurable parameters for PADIM anomaly classification task. """ diff --git a/external/anomaly/anomaly_classification/configs/padim/template.yaml b/external/anomaly/anomaly_classification/configs/padim/template.yaml index e328d209022..c5c33e6f0be 100644 --- a/external/anomaly/anomaly_classification/configs/padim/template.yaml +++ b/external/anomaly/anomaly_classification/configs/padim/template.yaml @@ -12,8 +12,8 @@ framework: OTEAnomalyClassification v0.1.0 # Task implementations. entrypoints: - base: anomaly_classification.AnomalyClassificationTask - openvino: anomaly_classification.OpenVINOAnomalyClassificationTask + base: ote_anomalib.BaseAnomalyTask + openvino: ote_anomalib.OpenVINOAnomalyTask # Hyper Parameters hyper_parameters: diff --git a/external/anomaly/anomaly_classification/configs/stfpm/__init__.py b/external/anomaly/anomaly_classification/configs/stfpm/__init__.py index 7e0fd46b66c..06759ff487e 100644 --- a/external/anomaly/anomaly_classification/configs/stfpm/__init__.py +++ b/external/anomaly/anomaly_classification/configs/stfpm/__init__.py @@ -17,6 +17,6 @@ # See the License for the specific language governing permissions # and limitations under the License. -from .configuration import STFPMConfig +from .configuration import STFPMAnomalyClassificationConfig -__all__ = ["STFPMConfig"] +__all__ = ["STFPMAnomalyClassificationConfig"] diff --git a/external/anomaly/anomaly_classification/configs/stfpm/configuration.py b/external/anomaly/anomaly_classification/configs/stfpm/configuration.py index 19566cf5d91..cc380f2c7f0 100644 --- a/external/anomaly/anomaly_classification/configs/stfpm/configuration.py +++ b/external/anomaly/anomaly_classification/configs/stfpm/configuration.py @@ -16,9 +16,9 @@ # See the License for the specific language governing permissions # and limitations under the License. -from anomaly_classification.configs.configuration import BaseAnomalyClassificationConfig -from anomaly_classification.configs.configuration_enums import EarlyStoppingMetrics from attr import attrs +from ote_anomalib.configs.configuration import BaseAnomalyConfig +from ote_anomalib.configs.configuration_enums import EarlyStoppingMetrics from ote_sdk.configuration.elements import ( ParameterGroup, add_parameter_group, @@ -30,7 +30,7 @@ @attrs -class STFPMConfig(BaseAnomalyClassificationConfig): +class STFPMAnomalyClassificationConfig(BaseAnomalyConfig): """ Configurable parameters for STFPM anomaly classification task. """ diff --git a/external/anomaly/anomaly_classification/configs/stfpm/template.yaml b/external/anomaly/anomaly_classification/configs/stfpm/template.yaml index 83a09345f66..ee742321f62 100644 --- a/external/anomaly/anomaly_classification/configs/stfpm/template.yaml +++ b/external/anomaly/anomaly_classification/configs/stfpm/template.yaml @@ -12,8 +12,8 @@ framework: OTEAnomalyClassification v0.1.0 # Task implementations. entrypoints: - base: anomaly_classification.AnomalyClassificationTask - openvino: anomaly_classification.OpenVINOAnomalyClassificationTask + base: ote_anomalib.BaseAnomalyTask + openvino: ote_anomalib.OpenVINOAnomalyTask # Hyper Parameters hyper_parameters: diff --git a/external/anomaly/anomaly_segmentation/__init__.py b/external/anomaly/anomaly_segmentation/__init__.py new file mode 100644 index 00000000000..3b0bced5886 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/__init__.py @@ -0,0 +1,17 @@ +""" +Initialization of Anomaly Segmentation Tasks +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. diff --git a/external/anomaly/anomaly_segmentation/configs/__init__.py b/external/anomaly/anomaly_segmentation/configs/__init__.py new file mode 100644 index 00000000000..9ac32c15eab --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/__init__.py @@ -0,0 +1,17 @@ +""" +Initialization of Configurable Parameters +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. diff --git a/external/anomaly/anomaly_classification/configs/configuration.py b/external/anomaly/anomaly_segmentation/configs/configuration.py similarity index 97% rename from external/anomaly/anomaly_classification/configs/configuration.py rename to external/anomaly/anomaly_segmentation/configs/configuration.py index b65e178f4ae..55730ac2176 100644 --- a/external/anomaly/anomaly_classification/configs/configuration.py +++ b/external/anomaly/anomaly_segmentation/configs/configuration.py @@ -18,8 +18,8 @@ from sys import maxsize -from anomaly_classification.configs.configuration_enums import POTQuantizationPreset from attr import attrs +from ote_anomalib.configs.configuration_enums import POTQuantizationPreset from ote_sdk.configuration import ConfigurableParameters from ote_sdk.configuration.elements import ( ParameterGroup, diff --git a/external/anomaly/anomaly_segmentation/configs/padim/__init__.py b/external/anomaly/anomaly_segmentation/configs/padim/__init__.py new file mode 100644 index 00000000000..30ccefe2994 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/padim/__init__.py @@ -0,0 +1,22 @@ +""" +Initialization of Configurable Parameters for PADIM +Anomaly Classification Task +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. + +from .configuration import PadimAnomalySegmentationConfig + +__all__ = ["PadimAnomalySegmentationConfig"] diff --git a/external/anomaly/anomaly_segmentation/configs/padim/configuration.py b/external/anomaly/anomaly_segmentation/configs/padim/configuration.py new file mode 100644 index 00000000000..7be758adb1b --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/padim/configuration.py @@ -0,0 +1,31 @@ +""" +Configurable parameters for Padim anomaly classification task +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. + +from attr import attrs +from ote_anomalib.configs.configuration import BaseAnomalyConfig +from ote_sdk.configuration.elements import string_attribute + + +@attrs +class PadimAnomalySegmentationConfig(BaseAnomalyConfig): + """ + Configurable parameters for PADIM anomaly classification task. + """ + + header = string_attribute("Configuration for Padim") + description = header diff --git a/external/anomaly/anomaly_segmentation/configs/padim/configuration.yaml b/external/anomaly/anomaly_segmentation/configs/padim/configuration.yaml new file mode 100644 index 00000000000..be5d120f060 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/padim/configuration.yaml @@ -0,0 +1,88 @@ +dataset: + description: Dataset Parameters + header: Dataset Parameters + num_workers: + affects_outcome_of: NONE + default_value: 8 + description: + Increasing this value might improve training speed however it might + cause out of memory errors. If the number of workers is set to zero, data loading + will happen in the main training thread. + editable: true + header: Number of workers + max_value: 36 + min_value: 0 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + train_batch_size: + affects_outcome_of: TRAINING + default_value: 32 + description: + The number of training samples seen in each iteration of training. + Increasing this value improves training time and may make the training more + stable. A larger batch size has higher memory requirements. + editable: true + header: Batch size + max_value: 512 + min_value: 1 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: + Increasing this value may cause the system to use more memory than available, + potentially causing out of memory errors, please update with caution. + type: PARAMETER_GROUP + visible_in_ui: true +description: Configuration for Padim +header: Configuration for Padim +pot_parameters: + description: POT Parameters + header: POT Parameters + preset: + affects_outcome_of: NONE + default_value: Performance + description: Quantization preset that defines quantization scheme + editable: true + enum_name: POTQuantizationPreset + header: Preset + options: + MIXED: Mixed + PERFORMANCE: Performance + type: SELECTABLE + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + stat_subset_size: + affects_outcome_of: NONE + default_value: 300 + description: Number of data samples used for post-training optimization + editable: true + header: Number of data samples + max_value: 9223372036854775807 + min_value: 1 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + type: PARAMETER_GROUP + visible_in_ui: true +type: CONFIGURABLE_PARAMETERS +visible_in_ui: true diff --git a/external/anomaly/anomaly_segmentation/configs/padim/pot_optimization_config.json b/external/anomaly/anomaly_segmentation/configs/padim/pot_optimization_config.json new file mode 100644 index 00000000000..dd70e63f9ff --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/padim/pot_optimization_config.json @@ -0,0 +1,18 @@ +{ + "algorithms": [ + { + "name": "DefaultQuantization", + "params": { + "preset": "performance", + "target_device": "ANY", + "range_estimator": { + "preset": "quantile" + }, + "ignored": { + "scope": ["Sqrt_105/pow_", "Mul_97"] + }, + "shuffle_data": true + } + } + ] +} diff --git a/external/anomaly/anomaly_segmentation/configs/padim/template.yaml b/external/anomaly/anomaly_segmentation/configs/padim/template.yaml new file mode 100644 index 00000000000..8ebf4e76ad2 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/padim/template.yaml @@ -0,0 +1,30 @@ +# Description. +model_template_id: ote_anomaly_segmentation_padim +name: PADIM +task_type: ANOMALY_SEGMENTATION +task_family: VISION +instantiation: "CLASS" +summary: This model is faster and in many cases more accurate, but it requires a fixed position of the objects within the image. +application: ~ + +# Algo backend. +framework: OTEAnomalyClassification v0.1.0 # TODO: update after the name has been changed on the platform side + +# Task implementations. +entrypoints: + base: ote_anomalib.BaseAnomalyTask + openvino: ote_anomalib.OpenVINOAnomalyTask + +# Hyper Parameters +hyper_parameters: + base_path: ./configuration.yaml + +# Training resources. +max_nodes: 1 +training_targets: + - GPU + - CPU + +# Computational Complexity +gigaflops: 3.9 +size: 168.4 diff --git a/external/anomaly/anomaly_segmentation/configs/stfpm/__init__.py b/external/anomaly/anomaly_segmentation/configs/stfpm/__init__.py new file mode 100644 index 00000000000..dc84c988874 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/stfpm/__init__.py @@ -0,0 +1,22 @@ +""" +Initialization of Configurable Parameters for STFPM +Anomaly Classification Task +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. + +from .configuration import STFPMAnomalySegmentationConfig + +__all__ = ["STFPMAnomalySegmentationConfig"] diff --git a/external/anomaly/anomaly_segmentation/configs/stfpm/configuration.py b/external/anomaly/anomaly_segmentation/configs/stfpm/configuration.py new file mode 100644 index 00000000000..df17aefc323 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/stfpm/configuration.py @@ -0,0 +1,80 @@ +""" +Configurable parameters for STFPM anomaly classification task +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. + +from attr import attrs +from ote_anomalib.configs.configuration import BaseAnomalyConfig +from ote_anomalib.configs.configuration_enums import EarlyStoppingMetrics +from ote_sdk.configuration.elements import ( + ParameterGroup, + add_parameter_group, + configurable_integer, + selectable, + string_attribute, +) +from ote_sdk.configuration.model_lifecycle import ModelLifecycle + + +@attrs +class STFPMAnomalySegmentationConfig(BaseAnomalyConfig): + """ + Configurable parameters for STFPM anomaly classification task. + """ + + header = string_attribute("Configuration for STFPM") + description = header + + @attrs + class ModelParameters(ParameterGroup): + """ + Parameter Group for training model + """ + + header = string_attribute("Model Parameters") + description = header + + @attrs + class EarlyStoppingParameters(ParameterGroup): + """ + Early stopping parameters + """ + + header = string_attribute("Early Stopping Parameters") + description = header + + metric = selectable( + default_value=EarlyStoppingMetrics.IMAGE_F1, + header="Early Stopping Metric", + description="The metric used to determine if the model should stop training", + ) + + patience = configurable_integer( + default_value=10, + min_value=1, + max_value=100, + header="Early Stopping Patience", + description="Number of epochs to wait for an improvement in the monitored metric. If the metric has " + "not improved for this many epochs, the training will stop and the best model will be " + "returned.", + warning="Setting this value too low might lead to underfitting. Setting the value too high will " + "increase the training time and might lead to overfitting.", + affects_outcome_of=ModelLifecycle.TRAINING, + ) + + early_stopping = add_parameter_group(EarlyStoppingParameters) + + model = add_parameter_group(ModelParameters) diff --git a/external/anomaly/anomaly_segmentation/configs/stfpm/configuration.yaml b/external/anomaly/anomaly_segmentation/configs/stfpm/configuration.yaml new file mode 100644 index 00000000000..f50e8c31acf --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/stfpm/configuration.yaml @@ -0,0 +1,137 @@ +dataset: + description: Dataset Parameters + header: Dataset Parameters + num_workers: + affects_outcome_of: NONE + default_value: 8 + description: + Increasing this value might improve training speed however it might + cause out of memory errors. If the number of workers is set to zero, data loading + will happen in the main training thread. + editable: true + header: Number of workers + max_value: 36 + min_value: 0 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + train_batch_size: + affects_outcome_of: TRAINING + default_value: 32 + description: + The number of training samples seen in each iteration of training. + Increasing this value improves training time and may make the training more + stable. A larger batch size has higher memory requirements. + editable: true + header: Batch size + max_value: 512 + min_value: 1 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: + Increasing this value may cause the system to use more memory than available, + potentially causing out of memory errors, please update with caution. + type: PARAMETER_GROUP + visible_in_ui: true +description: Configuration for STFPM +header: Configuration for STFPM +model: + description: Model Parameters + early_stopping: + description: Early Stopping Parameters + header: Early Stopping Parameters + metric: + affects_outcome_of: NONE + default_value: image_F1 + description: The metric used to determine if the model should stop training + editable: true + enum_name: EarlyStoppingMetrics + header: Early Stopping Metric + options: + IMAGE_F1: image_F1 + IMAGE_ROC_AUC: image_AUROC + type: SELECTABLE + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + patience: + affects_outcome_of: TRAINING + default_value: 10 + description: + Number of epochs to wait for an improvement in the monitored metric. + If the metric has not improved for this many epochs, the training will stop + and the best model will be returned. + editable: true + header: Early Stopping Patience + max_value: 100 + min_value: 1 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: + Setting this value too low might lead to underfitting. Setting the + value too high will increase the training time and might lead to overfitting. + type: PARAMETER_GROUP + visible_in_ui: true + header: Model Parameters + type: PARAMETER_GROUP + visible_in_ui: true +pot_parameters: + description: POT Parameters + header: POT Parameters + preset: + affects_outcome_of: NONE + default_value: Performance + description: Quantization preset that defines quantization scheme + editable: true + enum_name: POTQuantizationPreset + header: Preset + options: + MIXED: Mixed + PERFORMANCE: Performance + type: SELECTABLE + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + stat_subset_size: + affects_outcome_of: NONE + default_value: 300 + description: Number of data samples used for post-training optimization + editable: true + header: Number of data samples + max_value: 9223372036854775807 + min_value: 1 + type: INTEGER + ui_rules: + action: DISABLE_EDITING + operator: AND + rules: [] + type: UI_RULES + visible_in_ui: true + warning: null + type: PARAMETER_GROUP + visible_in_ui: true +type: CONFIGURABLE_PARAMETERS +visible_in_ui: true diff --git a/external/anomaly/anomaly_segmentation/configs/stfpm/template.yaml b/external/anomaly/anomaly_segmentation/configs/stfpm/template.yaml new file mode 100644 index 00000000000..644d435e2d0 --- /dev/null +++ b/external/anomaly/anomaly_segmentation/configs/stfpm/template.yaml @@ -0,0 +1,30 @@ +# Description. +model_template_id: ote_anomaly_segmentation_stfpm +name: STFPM +task_type: ANOMALY_SEGMENTATION +task_family: VISION +instantiation: "CLASS" +summary: Use this model when the position of the objects in the image frame might differ between images. +application: ~ + +# Algo backend. +framework: OTEAnomalyClassification v0.1.0 # TODO: update after the name has been changed on the platform side + +# Task implementations. +entrypoints: + base: ote_anomalib.BaseAnomalyTask + openvino: ote_anomalib.OpenVINOAnomalyTask + +# Hyper Parameters +hyper_parameters: + base_path: ./configuration.yaml + +# Training resources. +max_nodes: 1 +training_targets: + - GPU + - CPU + +# Computational Complexity +gigaflops: 5.6 +size: 21.1 diff --git a/external/anomaly/constraints.txt b/external/anomaly/constraints.txt index 399b403fa40..a23ed65cb8a 100644 --- a/external/anomaly/constraints.txt +++ b/external/anomaly/constraints.txt @@ -5,14 +5,14 @@ kornia==0.5.6 lxml==4.6.5 matplotlib==3.4.3 networkx~=2.5 -nncf==2.0.0 +nncf==2.1.0 numpy==1.19.5 omegaconf==2.1.1 onnx==1.10.1 opencv-python==4.5.3.56 -openvino-dev==2021.4.2 -pillow==8.3.2 -pytorch-lightning==1.3.6 +openvino-dev==2022.1.0.dev20220302 +pillow==9.0.0 +pytorch-lightning==1.5.9 requests==2.25.1 scikit-image==0.17.2 scikit-learn==0.24.2 diff --git a/external/anomaly/init_venv.sh b/external/anomaly/init_venv.sh index 6eaea273c49..015b677c8c2 100755 --- a/external/anomaly/init_venv.sh +++ b/external/anomaly/init_venv.sh @@ -100,11 +100,11 @@ pip install wheel || exit 1 pip install --upgrade setuptools || exit 1 if [[ -z $CUDA_VERSION_CODE ]]; then - pip install torch==${TORCH_VERSION}+cpu torchvision==${TORCHVISION_VERSION}+cpu -f https://download.pytorch.org/whl/torch_stable.html || exit 1 + pip install torch==${TORCH_VERSION}+cpu torchvision==${TORCHVISION_VERSION}+cpu -f https://download.pytorch.org/whl/torch_stable.html --no-cache || exit 1 echo torch==${TORCH_VERSION}+cpu >> ${CONSTRAINTS_FILE} echo torchvision==${TORCHVISION_VERSION}+cpu >> ${CONSTRAINTS_FILE} else - pip install torch==${TORCH_VERSION}+cu${CUDA_VERSION_CODE} torchvision==${TORCHVISION_VERSION}+cu${CUDA_VERSION_CODE} -f https://download.pytorch.org/whl/lts/1.8/torch_lts.html || exit 1 + pip install torch==${TORCH_VERSION}+cu${CUDA_VERSION_CODE} torchvision==${TORCHVISION_VERSION}+cu${CUDA_VERSION_CODE} -f https://download.pytorch.org/whl/lts/1.8/torch_lts.html --no-cache || exit 1 echo torch==${TORCH_VERSION}+cu${CUDA_VERSION_CODE} >> ${CONSTRAINTS_FILE} echo torchvision==${TORCHVISION_VERSION}+cu${CUDA_VERSION_CODE} >> ${CONSTRAINTS_FILE} fi diff --git a/external/anomaly/ote_anomalib/__init__.py b/external/anomaly/ote_anomalib/__init__.py index 1a202fb40b8..a90e7dcb2fa 100644 --- a/external/anomaly/ote_anomalib/__init__.py +++ b/external/anomaly/ote_anomalib/__init__.py @@ -15,3 +15,8 @@ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions # and limitations under the License. + +from .openvino import OpenVINOAnomalyTask +from .task import BaseAnomalyTask + +__all__ = ["BaseAnomalyTask", "OpenVINOAnomalyTask"] diff --git a/external/anomaly/ote_anomalib/callbacks/__init__.py b/external/anomaly/ote_anomalib/callbacks/__init__.py index 8e2807f8b6c..4d4fc9b2e79 100644 --- a/external/anomaly/ote_anomalib/callbacks/__init__.py +++ b/external/anomaly/ote_anomalib/callbacks/__init__.py @@ -16,7 +16,7 @@ # See the License for the specific language governing permissions # and limitations under the License. -from .inference import InferenceCallback +from .inference import AnomalyInferenceCallback from .progress import ProgressCallback -__all__ = ["InferenceCallback", "ProgressCallback"] +__all__ = ["AnomalyInferenceCallback", "ProgressCallback"] diff --git a/external/anomaly/ote_anomalib/callbacks/inference.py b/external/anomaly/ote_anomalib/callbacks/inference.py index b1a238a84d3..1227f56b8ad 100644 --- a/external/anomaly/ote_anomalib/callbacks/inference.py +++ b/external/anomaly/ote_anomalib/callbacks/inference.py @@ -20,26 +20,30 @@ import numpy as np import pytorch_lightning as pl -from anomalib.core.model.anomaly_module import AnomalyModule -from anomalib.utils.post_process import anomaly_map_to_color_map +from anomalib.models import AnomalyModule +from anomalib.post_processing import anomaly_map_to_color_map from ote_anomalib.data import LabelNames from ote_anomalib.logging import get_logger from ote_sdk.entities.datasets import DatasetEntity from ote_sdk.entities.label import LabelEntity +from ote_sdk.entities.model_template import TaskType from ote_sdk.entities.result_media import ResultMediaEntity from ote_sdk.entities.scored_label import ScoredLabel +from ote_sdk.utils.segmentation_utils import create_annotation_from_segmentation_map from pytorch_lightning.callbacks import Callback logger = get_logger(__name__) -class InferenceCallback(Callback): +class AnomalyInferenceCallback(Callback): """Callback that updates the OTE dataset during inference.""" - def __init__(self, ote_dataset: DatasetEntity, labels: List[LabelEntity]): + def __init__(self, ote_dataset: DatasetEntity, labels: List[LabelEntity], task_type: TaskType): self.ote_dataset = ote_dataset self.normal_label = [label for label in labels if label.name == LabelNames.normal][0] self.anomalous_label = [label for label in labels if label.name == LabelNames.anomalous][0] + self.task_type = task_type + self.label_map = {0: self.normal_label, 1: self.anomalous_label} def on_predict_epoch_end(self, _trainer: pl.Trainer, pl_module: AnomalyModule, outputs: List[Any]): """Call when the predict epoch ends.""" @@ -47,23 +51,32 @@ def on_predict_epoch_end(self, _trainer: pl.Trainer, pl_module: AnomalyModule, o pred_scores = np.hstack([output["pred_scores"].cpu() for output in outputs]) pred_labels = np.hstack([output["pred_labels"].cpu() for output in outputs]) anomaly_maps = np.vstack([output["anomaly_maps"].cpu() for output in outputs]) + pred_masks = np.vstack([output["pred_masks"].cpu() for output in outputs]) # Loop over dataset again to assign predictions - for dataset_item, pred_score, pred_label, anomaly_map in zip( - self.ote_dataset, pred_scores, pred_labels, anomaly_maps + for dataset_item, pred_score, pred_label, anomaly_map, pred_mask in zip( + self.ote_dataset, pred_scores, pred_labels, anomaly_maps, pred_masks ): label = self.anomalous_label if pred_label else self.normal_label - probability = (1 - pred_score) if pred_score < 0.5 else pred_score - dataset_item.append_labels([ScoredLabel(label=label, probability=float(probability))]) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + probability = (1 - pred_score) if pred_score < 0.5 else pred_score + dataset_item.append_labels([ScoredLabel(label=label, probability=float(probability))]) + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + mask = pred_mask.squeeze().astype(np.uint8) + dataset_item.append_annotations( + create_annotation_from_segmentation_map(mask, anomaly_map.squeeze(), self.label_map) + ) + else: + raise ValueError(f"Unknown task type: {self.task_type}") - heatmap = anomaly_map_to_color_map(anomaly_map.squeeze(), normalize=False) - heatmap_media = ResultMediaEntity( - name="Anomaly Map", - type="anomaly_map", - annotation_scene=dataset_item.annotation_scene, - numpy=heatmap, + dataset_item.append_metadata_item( + ResultMediaEntity( + name="Anomaly Map", + type="anomaly_map", + annotation_scene=dataset_item.annotation_scene, + numpy=anomaly_map_to_color_map(anomaly_map.squeeze(), normalize=False), + ) ) - dataset_item.append_metadata_item(heatmap_media) logger.info( "\n\tMin: %.3f, Max: %.3f, Threshold: %.3f, Assigned Label '%s', %.3f", pl_module.min_max.min.item(), diff --git a/external/anomaly/ote_anomalib/callbacks/progress.py b/external/anomaly/ote_anomalib/callbacks/progress.py index 4d195b8ab4d..608ab6bca0a 100644 --- a/external/anomaly/ote_anomalib/callbacks/progress.py +++ b/external/anomaly/ote_anomalib/callbacks/progress.py @@ -62,11 +62,11 @@ def on_test_start(self, trainer, pl_module): super().on_test_start(trainer, pl_module) self._reset_progress() - def on_train_batch_end(self, trainer, pl_module, outputs, batch, batch_idx, dataloader_idx): + def on_train_batch_end(self, trainer, pl_module, outputs, batch, batch_idx): """ Adds training completion percentage to the progress bar """ - super().on_train_batch_end(trainer, pl_module, outputs, batch, batch_idx, dataloader_idx) + super().on_train_batch_end(trainer, pl_module, outputs, batch, batch_idx) self.current_epoch = trainer.current_epoch self._update_progress(stage="train") diff --git a/external/anomaly/ote_anomalib/config/__init__.py b/external/anomaly/ote_anomalib/configs/__init__.py similarity index 93% rename from external/anomaly/ote_anomalib/config/__init__.py rename to external/anomaly/ote_anomalib/configs/__init__.py index e6c7c97c4cc..565b4d9df4d 100644 --- a/external/anomaly/ote_anomalib/config/__init__.py +++ b/external/anomaly/ote_anomalib/configs/__init__.py @@ -16,6 +16,6 @@ # See the License for the specific language governing permissions # and limitations under the License. -from .config import get_anomalib_config +from .anomalib_config import get_anomalib_config __all__ = ["get_anomalib_config"] diff --git a/external/anomaly/ote_anomalib/config/config.py b/external/anomaly/ote_anomalib/configs/anomalib_config.py similarity index 100% rename from external/anomaly/ote_anomalib/config/config.py rename to external/anomaly/ote_anomalib/configs/anomalib_config.py diff --git a/external/anomaly/ote_anomalib/configs/configuration.py b/external/anomaly/ote_anomalib/configs/configuration.py new file mode 100644 index 00000000000..34381c80173 --- /dev/null +++ b/external/anomaly/ote_anomalib/configs/configuration.py @@ -0,0 +1,99 @@ +""" +Configurable parameters for anomaly classification task +""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. + +from sys import maxsize + +from attr import attrs +from ote_anomalib.configs.configuration_enums import POTQuantizationPreset +from ote_sdk.configuration import ConfigurableParameters +from ote_sdk.configuration.elements import ( + ParameterGroup, + add_parameter_group, + configurable_integer, + selectable, + string_attribute, +) +from ote_sdk.configuration.model_lifecycle import ModelLifecycle + + +@attrs +class BaseAnomalyConfig(ConfigurableParameters): + """ + Base OTE configurable parameters for anomaly classification task. + """ + + header = string_attribute("Configuration for an anomaly classification task") + description = header + + @attrs + class DatasetParameters(ParameterGroup): + """ + Parameters related to dataloader + """ + + header = string_attribute("Dataset Parameters") + description = header + + train_batch_size = configurable_integer( + default_value=32, + min_value=1, + max_value=512, + header="Batch size", + description="The number of training samples seen in each iteration of training. Increasing this value " + "improves training time and may make the training more stable. A larger batch size has higher " + "memory requirements.", + warning="Increasing this value may cause the system to use more memory than available, " + "potentially causing out of memory errors, please update with caution.", + affects_outcome_of=ModelLifecycle.TRAINING, + ) + + num_workers = configurable_integer( + default_value=8, + min_value=0, + max_value=36, + header="Number of workers", + description="Increasing this value might improve training speed however it might cause out of memory " + "errors. If the number of workers is set to zero, data loading will happen in the main " + "training thread.", + ) + + @attrs + class POTParameters(ParameterGroup): + """ + Training parameters for post-training optimization + """ + + header = string_attribute("POT Parameters") + description = header + + preset = selectable( + default_value=POTQuantizationPreset.PERFORMANCE, + header="Preset", + description="Quantization preset that defines quantization scheme", + ) + + stat_subset_size = configurable_integer( + header="Number of data samples", + description="Number of data samples used for post-training optimization", + default_value=300, + min_value=1, + max_value=maxsize, + ) + + dataset = add_parameter_group(DatasetParameters) + pot_parameters = add_parameter_group(POTParameters) diff --git a/external/anomaly/anomaly_classification/configs/configuration_enums.py b/external/anomaly/ote_anomalib/configs/configuration_enums.py similarity index 100% rename from external/anomaly/anomaly_classification/configs/configuration_enums.py rename to external/anomaly/ote_anomalib/configs/configuration_enums.py diff --git a/external/anomaly/ote_anomalib/data/data.py b/external/anomaly/ote_anomalib/data/data.py index d20dd78acf0..2e62f4e6430 100644 --- a/external/anomaly/ote_anomalib/data/data.py +++ b/external/anomaly/ote_anomalib/data/data.py @@ -19,11 +19,15 @@ from dataclasses import dataclass from typing import Dict, List, Optional, Union -from anomalib.data.transforms import PreProcessor +import numpy as np +from anomalib.pre_processing import PreProcessor from omegaconf import DictConfig, ListConfig from ote_anomalib.logging import get_logger from ote_sdk.entities.datasets import DatasetEntity +from ote_sdk.entities.model_template import TaskType +from ote_sdk.entities.shapes.polygon import Polygon from ote_sdk.entities.subset import Subset +from ote_sdk.utils.segmentation_utils import mask_from_dataset_item from pytorch_lightning.core.datamodule import LightningDataModule from torch import Tensor from torch.utils.data import DataLoader, Dataset @@ -63,9 +67,10 @@ class OTEAnomalyDataset(Dataset): torch.Size([3, 256, 256]) """ - def __init__(self, config: Union[DictConfig, ListConfig], dataset: DatasetEntity): + def __init__(self, config: Union[DictConfig, ListConfig], dataset: DatasetEntity, task_type: TaskType): self.config = config self.dataset = dataset + self.task_type = task_type self.pre_processor = PreProcessor( config=config.transform if "transform" in config.keys() else None, @@ -77,13 +82,24 @@ def __len__(self) -> int: return len(self.dataset) def __getitem__(self, index: int) -> Dict[str, Union[int, Tensor]]: - item = self.dataset[index] - image = self.pre_processor(image=item.numpy)["image"] - try: - label = 0 if item.get_shapes_labels()[0].name == LabelNames.normal else 1 - except IndexError: - return {"index": index, "image": image} - return {"index": index, "image": image, "label": label} + dataset_item = self.dataset[index] + item = {"index": index} + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + item["image"] = self.pre_processor(image=dataset_item.numpy)["image"] + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + if any((isinstance(annotation.shape, Polygon) for annotation in dataset_item.get_annotations())): + mask = mask_from_dataset_item(dataset_item, dataset_item.get_shapes_labels()).squeeze() + else: + mask = np.zeros(dataset_item.numpy.shape[:2]).astype(np.int) + pre_processed = self.pre_processor(image=dataset_item.numpy, mask=mask) + item["image"] = pre_processed["image"] + item["mask"] = pre_processed["mask"] + else: + raise ValueError(f"Unsupported task type: {self.config.dataset.task}") + + if len(dataset_item.get_shapes_labels()) > 0: + item["label"] = 1 if dataset_item.get_shapes_labels()[0].is_anomalous else 0 + return item class OTEAnomalyDataModule(LightningDataModule): @@ -108,10 +124,11 @@ class OTEAnomalyDataModule(LightningDataModule): torch.Size([32, 3, 256, 256]) """ - def __init__(self, config: Union[DictConfig, ListConfig], dataset: DatasetEntity) -> None: + def __init__(self, config: Union[DictConfig, ListConfig], dataset: DatasetEntity, task_type: TaskType) -> None: super().__init__() self.config = config self.dataset = dataset + self.task_type = task_type self.train_ote_dataset: DatasetEntity self.val_ote_dataset: DatasetEntity @@ -166,7 +183,7 @@ def train_dataloader( Train Dataloader """ - dataset = OTEAnomalyDataset(self.config, self.train_ote_dataset) + dataset = OTEAnomalyDataset(self.config, self.train_ote_dataset, self.task_type) return DataLoader( dataset, shuffle=False, @@ -179,7 +196,7 @@ def val_dataloader(self) -> Union[DataLoader, List[DataLoader]]: Validation Dataloader """ - dataset = OTEAnomalyDataset(self.config, self.val_ote_dataset) + dataset = OTEAnomalyDataset(self.config, self.val_ote_dataset, self.task_type) return DataLoader( dataset, shuffle=False, @@ -191,7 +208,7 @@ def test_dataloader(self) -> Union[DataLoader, List[DataLoader]]: """ Test Dataloader """ - dataset = OTEAnomalyDataset(self.config, self.test_ote_dataset) + dataset = OTEAnomalyDataset(self.config, self.test_ote_dataset, self.task_type) return DataLoader( dataset, shuffle=False, @@ -203,7 +220,7 @@ def predict_dataloader(self) -> Union[DataLoader, List[DataLoader]]: """ Predict Dataloader """ - dataset = OTEAnomalyDataset(self.config, self.predict_ote_dataset) + dataset = OTEAnomalyDataset(self.config, self.predict_ote_dataset, self.task_type) return DataLoader( dataset, shuffle=False, diff --git a/external/anomaly/ote_anomalib/data/mvtec.py b/external/anomaly/ote_anomalib/data/mvtec.py index 9ffc669700c..80580d96abb 100644 --- a/external/anomaly/ote_anomalib/data/mvtec.py +++ b/external/anomaly/ote_anomalib/data/mvtec.py @@ -17,6 +17,8 @@ from pathlib import Path from typing import List, Union +import cv2 +import numpy as np from anomalib.data.mvtec import make_mvtec_dataset from ote_anomalib.data import LabelNames from ote_sdk.entities.annotation import ( @@ -24,14 +26,17 @@ AnnotationSceneEntity, AnnotationSceneKind, ) +from ote_sdk.entities.color import Color from ote_sdk.entities.dataset_item import DatasetItemEntity from ote_sdk.entities.datasets import DatasetEntity from ote_sdk.entities.id import ID from ote_sdk.entities.image import Image from ote_sdk.entities.label import Domain, LabelEntity +from ote_sdk.entities.model_template import TaskType from ote_sdk.entities.scored_label import ScoredLabel from ote_sdk.entities.shapes.rectangle import Rectangle from ote_sdk.entities.subset import Subset +from ote_sdk.utils.segmentation_utils import create_annotation_from_segmentation_map from pandas.core.frame import DataFrame @@ -53,24 +58,37 @@ class OteMvtecDataset: (900, 900, 3) """ + # pylint: disable=too-many-instance-attributes def __init__( self, path: Union[str, Path], split_ratio: float = 0.5, seed: int = 0, create_validation_set: bool = True, + task_type: TaskType = TaskType.ANOMALY_CLASSIFICATION, ): self.path = path if isinstance(path, Path) else Path(path) self.split_ratio = split_ratio self.seed = seed self.create_validation_set = create_validation_set + self.task_type = task_type + + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + self.label_domain = Domain.ANOMALY_SEGMENTATION + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + self.label_domain = Domain.ANOMALY_SEGMENTATION self.normal_label = LabelEntity( - name=LabelNames.normal, domain=Domain.ANOMALY_CLASSIFICATION, id=ID(LabelNames.normal) + name=LabelNames.normal, domain=self.label_domain, id=ID(LabelNames.normal), color=Color(0, 255, 0) ) self.abnormal_label = LabelEntity( - name=LabelNames.anomalous, domain=Domain.ANOMALY_CLASSIFICATION, id=ID(LabelNames.anomalous) + name=LabelNames.anomalous, + domain=self.label_domain, + id=ID(LabelNames.anomalous), + is_anomalous=True, + color=Color(255, 0, 0), ) + self.label_map = {0: self.normal_label, 1: self.abnormal_label} def get_samples(self) -> DataFrame: """Get MVTec samples. @@ -115,10 +133,17 @@ def generate(self) -> DatasetEntity: image = Image(file_path=sample.image_path) # Create annotation - shape = Rectangle(x1=0, y1=0, x2=1, y2=1) - labels = [ScoredLabel(sample.label)] - annotations = [Annotation(shape=shape, labels=labels)] - annotation_scene = AnnotationSceneEntity(annotations=annotations, kind=AnnotationSceneKind.ANNOTATION) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION or sample.label == self.normal_label: + shape = Rectangle(x1=0, y1=0, x2=1, y2=1) + labels = [ScoredLabel(sample.label)] + annotations = [Annotation(shape=shape, labels=labels)] + annotation_scene = AnnotationSceneEntity(annotations=annotations, kind=AnnotationSceneKind.ANNOTATION) + elif self.task_type == TaskType.ANOMALY_SEGMENTATION and sample.label == self.abnormal_label: + mask = (cv2.imread(sample.mask_path, cv2.IMREAD_GRAYSCALE) / 255).astype(np.uint8) + annotations = create_annotation_from_segmentation_map(mask, np.ones_like(mask), self.label_map) + annotation_scene = AnnotationSceneEntity(annotations=annotations, kind=AnnotationSceneKind.ANNOTATION) + else: + raise ValueError(f"Unknown task type: {self.task_type}") # Create dataset item dataset_item = DatasetItemEntity(media=image, annotation_scene=annotation_scene, subset=sample.subset) diff --git a/external/anomaly/ote_anomalib/exportable_code/__init__.py b/external/anomaly/ote_anomalib/exportable_code/__init__.py index bd9165a990a..cfb984e730b 100644 --- a/external/anomaly/ote_anomalib/exportable_code/__init__.py +++ b/external/anomaly/ote_anomalib/exportable_code/__init__.py @@ -1,5 +1,11 @@ """Exportable code for Anomaly tasks.""" +# Copyright (C) 2021-2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + from .anomaly_classification import AnomalyClassification +from .anomaly_segmentation import AnomalySegmentation +from .base import AnomalyBase -__all__ = ["AnomalyClassification"] +__all__ = ["AnomalyBase", "AnomalySegmentation", "AnomalyClassification"] diff --git a/external/anomaly/ote_anomalib/exportable_code/anomaly_classification.py b/external/anomaly/ote_anomalib/exportable_code/anomaly_classification.py index d783a033579..2d3caee2845 100644 --- a/external/anomaly/ote_anomalib/exportable_code/anomaly_classification.py +++ b/external/anomaly/ote_anomalib/exportable_code/anomaly_classification.py @@ -1,54 +1,22 @@ -"""Wrapper for Open Model Zoo for Anomaly tasks.""" +"""Wrapper for Open Model Zoo for Anomaly Classification tasks.""" # Copyright (C) 2021-2022 Intel Corporation # SPDX-License-Identifier: Apache-2.0 # -from typing import Any, Dict, Union +from typing import Any, Dict import cv2 import numpy as np -from openvino.model_zoo.model_api.models import SegmentationModel -from openvino.model_zoo.model_api.models.types import NumericalValue +from .base import AnomalyBase -class AnomalyClassification(SegmentationModel): + +class AnomalyClassification(AnomalyBase): """Wrapper for anomaly classification task.""" __model__ = "anomaly_classification" - @classmethod - def parameters(cls): - """Dictionary containing model parameters.""" - parameters = super().parameters() - parameters["resize_type"].update_default_value("standard") - parameters.update( - { - "image_threshold": NumericalValue(description="Threshold value to locate anomaly"), - "min": NumericalValue(description="Threshold value to locate anomaly"), - "max": NumericalValue(description="Threshold value to locate anomaly"), - "threshold": NumericalValue(description="Threshold used to classify anomaly"), - } - ) - - return parameters - - @staticmethod - def _normalize( - targets: Union[np.ndarray, np.float32], - threshold: Union[np.ndarray, float], - min_val: Union[np.ndarray, float], - max_val: Union[np.ndarray, float], - ) -> np.ndarray: - """Apply min-max normalization and shift the values such that the threshold value is centered at 0.5.""" - normalized = ((targets - threshold) / (max_val - min_val)) + 0.5 - if isinstance(targets, (np.ndarray, np.float32)): - normalized = np.minimum(normalized, 1) - normalized = np.maximum(normalized, 0) - else: - raise ValueError(f"Targets must be either Tensor or Numpy array. Received {type(targets)}") - return normalized - def postprocess(self, outputs: Dict[str, np.ndarray], meta: Dict[str, Any]) -> float: """Resize the outputs of the model to original image size. diff --git a/external/anomaly/ote_anomalib/exportable_code/anomaly_segmentation.py b/external/anomaly/ote_anomalib/exportable_code/anomaly_segmentation.py new file mode 100644 index 00000000000..c260ddea6a7 --- /dev/null +++ b/external/anomaly/ote_anomalib/exportable_code/anomaly_segmentation.py @@ -0,0 +1,43 @@ +"""Wrapper for Open Model Zoo for Anomaly Segmentation tasks.""" + +# Copyright (C) 2021-2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +from typing import Any, Dict + +import cv2 +import numpy as np + +from .base import AnomalyBase + + +class AnomalySegmentation(AnomalyBase): + """Wrapper for anomaly segmentation task.""" + + __model__ = "anomaly_segmentation" + + def postprocess(self, outputs: Dict[str, np.ndarray], meta: Dict[str, Any]) -> np.ndarray: + """Resize the outputs of the model to original image size. + + Args: + outputs (Dict[str, np.ndarray]): Raw outputs of the model after ``infer_sync`` is called. + meta (Dict[str, Any]): Metadata which contains values such as threshold, original image size. + + Returns: + np.ndarray: Segmentation Mask + """ + anomaly_map: np.ndarray = outputs[self.output_blob_name].squeeze() + + meta["pixel_threshold"] = self.pixel_threshold # pylint: disable=no-member + meta["min"] = self.min # pylint: disable=no-member + meta["max"] = self.max # pylint: disable=no-member + meta["threshold"] = self.threshold # pylint: disable=no-member + + anomaly_map = self._normalize(anomaly_map, meta["pixel_threshold"], meta["min"], meta["max"]) + + input_image_height = meta["original_shape"][0] + input_image_width = meta["original_shape"][1] + result = cv2.resize(anomaly_map, (input_image_width, input_image_height)) + + return result diff --git a/external/anomaly/ote_anomalib/exportable_code/base.py b/external/anomaly/ote_anomalib/exportable_code/base.py new file mode 100644 index 00000000000..0c065e91efe --- /dev/null +++ b/external/anomaly/ote_anomalib/exportable_code/base.py @@ -0,0 +1,50 @@ +"""Wrapper for Open Model Zoo for Anomaly tasks.""" + +# Copyright (C) 2021-2022 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 +# + +from typing import Union + +import numpy as np +from openvino.model_zoo.model_api.models import SegmentationModel +from openvino.model_zoo.model_api.models.types import NumericalValue + + +class AnomalyBase(SegmentationModel): + """Wrapper for anomaly tasks.""" + + __model__ = "anomaly_base" + + @classmethod + def parameters(cls): + """Dictionary containing model parameters.""" + parameters = super().parameters() + parameters["resize_type"].update_default_value("standard") + parameters.update( + { + "image_threshold": NumericalValue(description="Image-level Threshold value to locate anomaly"), + "pixel_threshold": NumericalValue(description="Pixel-level Threshold value to locate anomaly"), + "min": NumericalValue(description="Threshold value to locate anomaly"), + "max": NumericalValue(description="Threshold value to locate anomaly"), + "threshold": NumericalValue(description="Threshold used to classify anomaly"), + } + ) + + return parameters + + @staticmethod + def _normalize( + targets: Union[np.ndarray, np.float32], + threshold: Union[np.ndarray, float], + min_val: Union[np.ndarray, float], + max_val: Union[np.ndarray, float], + ) -> np.ndarray: + """Apply min-max normalization and shift the values such that the threshold value is centered at 0.5.""" + normalized = ((targets - threshold) / (max_val - min_val)) + 0.5 + if isinstance(targets, (np.ndarray, np.float32)): + normalized = np.minimum(normalized, 1) + normalized = np.maximum(normalized, 0) + else: + raise ValueError(f"Targets must be either Tensor or Numpy array. Received {type(targets)}") + return normalized diff --git a/external/anomaly/anomaly_classification/openvino.py b/external/anomaly/ote_anomalib/openvino.py similarity index 81% rename from external/anomaly/anomaly_classification/openvino.py rename to external/anomaly/ote_anomalib/openvino.py index 4d244c2f58f..32d407c6c9c 100644 --- a/external/anomaly/anomaly_classification/openvino.py +++ b/external/anomaly/ote_anomalib/openvino.py @@ -23,22 +23,25 @@ import sys import tempfile from shutil import copyfile, copytree -from typing import Any, Dict, List, Optional, Union +from typing import Any, Dict, List, Optional from zipfile import ZipFile import numpy as np from addict import Dict as ADDict -from anomalib.core.model.inference import OpenVINOInferencer -from anomalib.utils.post_process import anomaly_map_to_color_map +from anomalib.deploy import OpenVINOInferencer +from anomalib.post_processing import anomaly_map_to_color_map from compression.api import DataLoader from compression.engines.ie_engine import IEEngine from compression.graph import load_model, save_model from compression.graph.model_utils import compress_model_weights, get_nodes_by_type from compression.pipeline.initializer import create_pipeline -from omegaconf import ListConfig -from omegaconf.dictconfig import DictConfig -from ote_anomalib.config import get_anomalib_config -from ote_anomalib.exportable_code import AnomalyClassification +from omegaconf import OmegaConf +from ote_anomalib.configs import get_anomalib_config +from ote_anomalib.exportable_code import ( + AnomalyBase, + AnomalyClassification, + AnomalySegmentation, +) from ote_anomalib.logging import get_logger from ote_sdk.entities.datasets import DatasetEntity from ote_sdk.entities.inference_parameters import ( @@ -52,17 +55,19 @@ ModelPrecision, OptimizationMethod, ) +from ote_sdk.entities.model_template import TaskType from ote_sdk.entities.optimization_parameters import OptimizationParameters from ote_sdk.entities.result_media import ResultMediaEntity from ote_sdk.entities.resultset import ResultSetEntity from ote_sdk.entities.task_environment import TaskEnvironment from ote_sdk.serialization.label_mapper import LabelSchemaMapper, label_schema_to_bytes +from ote_sdk.usecases.evaluation.averaging import MetricAverageMethod from ote_sdk.usecases.evaluation.metrics_helper import MetricsHelper from ote_sdk.usecases.exportable_code import demo from ote_sdk.usecases.exportable_code.prediction_to_annotation_converter import ( AnomalyClassificationToAnnotationConverter, + AnomalySegmentationToAnnotationConverter, ) -from ote_sdk.usecases.exportable_code.utils import set_proper_git_commit_hash from ote_sdk.usecases.tasks.interfaces.deployment_interface import IDeploymentTask from ote_sdk.usecases.tasks.interfaces.evaluate_interface import IEvaluationTask from ote_sdk.usecases.tasks.interfaces.inference_interface import IInferenceTask @@ -85,7 +90,7 @@ class OTEOpenVINOAnomalyDataloader(DataLoader): def __init__( self, - config: Union[DictConfig, ListConfig], + config: ADDict, dataset: DatasetEntity, inferencer: OpenVINOInferencer, ): @@ -104,7 +109,7 @@ def __len__(self): return len(self.dataset) -class OpenVINOAnomalyClassificationTask(IInferenceTask, IEvaluationTask, IOptimizationTask, IDeploymentTask): +class OpenVINOAnomalyTask(IInferenceTask, IEvaluationTask, IOptimizationTask, IDeploymentTask): """ OpenVINO inference task @@ -115,23 +120,29 @@ class OpenVINOAnomalyClassificationTask(IInferenceTask, IEvaluationTask, IOptimi def __init__(self, task_environment: TaskEnvironment) -> None: logger.info("Initializing the OpenVINO task.") self.task_environment = task_environment + self.task_type = self.task_environment.model_template.task_type self.config = self.get_config() self.inferencer = self.load_inferencer() - self.annotation_converter = AnomalyClassificationToAnnotationConverter(self.task_environment.label_schema) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + self.annotation_converter = AnomalyClassificationToAnnotationConverter(self.task_environment.label_schema) + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + self.annotation_converter = AnomalySegmentationToAnnotationConverter(self.task_environment.label_schema) + else: + raise ValueError(f"Unknown task type: {self.task_type}") template_file_path = task_environment.model_template.model_template_path self._base_dir = os.path.abspath(os.path.dirname(template_file_path)) - def get_config(self) -> Union[DictConfig, ListConfig]: + def get_config(self) -> ADDict: """ Get Anomalib Config from task environment Returns: - Union[DictConfig, ListConfig]: Anomalib config + ADDict: Anomalib config """ task_name = self.task_environment.model_template.name ote_config = self.task_environment.get_hyper_parameters() config = get_anomalib_config(task_name=task_name, ote_config=ote_config) - return config + return ADDict(OmegaConf.to_container(config)) def infer(self, dataset: DatasetEntity, inference_parameters: InferenceParameters) -> DatasetEntity: """Perform Inference. @@ -157,8 +168,16 @@ def infer(self, dataset: DatasetEntity, inference_parameters: InferenceParameter anomaly_map, pred_score = self.inferencer.predict( dataset_item.numpy, superimpose=False, meta_data=meta_data ) - annotations_scene = self.annotation_converter.convert_to_annotation(pred_score, meta_data) - dataset_item.append_labels(annotations_scene.annotations[0].get_labels()) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + annotations_scene = self.annotation_converter.convert_to_annotation(pred_score, meta_data) + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + annotations_scene = self.annotation_converter.convert_to_annotation(anomaly_map, meta_data) + else: + raise ValueError(f"Unknown task type: {self.task_type}") + + # pylint: disable=protected-access + dataset_item.append_annotations(annotations_scene.annotations) + anomaly_map = anomaly_map_to_color_map(anomaly_map, normalize=False) heatmap_media = ResultMediaEntity( name="Anomaly Map", @@ -175,11 +194,12 @@ def get_meta_data(self): """Get Meta Data.""" image_threshold = np.frombuffer(self.task_environment.model.get_data("image_threshold"), dtype=np.float32) + pixel_threshold = np.frombuffer(self.task_environment.model.get_data("pixel_threshold"), dtype=np.float32) min_value = np.frombuffer(self.task_environment.model.get_data("min"), dtype=np.float32) max_value = np.frombuffer(self.task_environment.model.get_data("max"), dtype=np.float32) meta_data = dict( image_threshold=image_threshold, - pixel_threshold=image_threshold, # re-use image threshold for pixel normalization + pixel_threshold=pixel_threshold, min=min_value, max=max_value, ) @@ -192,19 +212,14 @@ def evaluate(self, output_resultset: ResultSetEntity, evaluation_metric: Optiona output_resultset (ResultSetEntity): Result set storing ground truth and predicted dataset. evaluation_metric (Optional[str], optional): Evaluation metric. Defaults to None. """ - metric = MetricsHelper.compute_f_measure(output_resultset) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + metric = MetricsHelper.compute_f_measure(output_resultset) + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + metric = MetricsHelper.compute_dice_averaged_over_pixels(output_resultset, MetricAverageMethod.MICRO) + else: + raise ValueError(f"Unknown task type: {self.task_type}") output_resultset.performance = metric.get_performance() - # NOTE: This is for debugging purpose. - for i, _ in enumerate(output_resultset.ground_truth_dataset): - logger.info( - "True vs Pred: %s %s - %3.2f", - output_resultset.ground_truth_dataset[i].annotation_scene.annotations[0].get_labels()[0].name, - output_resultset.prediction_dataset[i].annotation_scene.annotations[0].get_labels()[0].name, - output_resultset.prediction_dataset[i].annotation_scene.annotations[0].get_labels()[0].probability, - ) - logger.info("%s performance of the OpenVINO model: %3.2f", metric.f_measure.name, metric.f_measure.value) - def _get_optimization_algorithms_configs(self) -> List[ADDict]: """Returns list of optimization algorithms configurations""" @@ -279,6 +294,7 @@ def optimize( output_model.set_data("label_schema.json", label_schema_to_bytes(self.task_environment.label_schema)) output_model.set_data("image_threshold", self.task_environment.model.get_data("image_threshold")) + output_model.set_data("pixel_threshold", self.task_environment.model.get_data("pixel_threshold")) output_model.set_data("min", self.task_environment.model.get_data("min")) output_model.set_data("max", self.task_environment.model.get_data("max")) output_model.model_format = ModelFormat.OPENVINO @@ -332,8 +348,9 @@ def __load_weights(path: str, output_model: ModelEntity, key: str) -> None: def _get_openvino_configuration(self) -> Dict[str, Any]: """Return configuration required by the exported model.""" - # This always assumes that threshold is available in the task environment's model - # cast is used to placate mypy + if self.task_environment.model is None: + raise Exception("task_environment.model is None. Cannot get configuration.") + configuration = { "image_threshold": np.frombuffer( self.task_environment.model.get_data("image_threshold"), dtype=np.float32 @@ -349,6 +366,16 @@ def _get_openvino_configuration(self) -> Dict[str, Any]: else: configuration["mean_values"] = self.config.transforms.mean configuration["scale_values"] = self.config.transforms.std + + if "pixel_threshold" in self.task_environment.model.model_adapters.keys(): + configuration["pixel_threshold"] = np.frombuffer( + self.task_environment.model.get_data("pixel_threshold"), dtype=np.float32 + ).item() + else: + configuration["pixel_threshold"] = np.frombuffer( + self.task_environment.model.get_data("image_threshold"), dtype=np.float32 + ).item() + return configuration def deploy(self, output_model: ModelEntity) -> None: @@ -367,21 +394,27 @@ def deploy(self, output_model: ModelEntity) -> None: work_dir = os.path.dirname(demo.__file__) parameters: Dict[str, Any] = {} - parameters["type_of_model"] = "anomaly_classification" - parameters["converter_type"] = "ANOMALY_CLASSIFICATION" + task_type = ( + "anomaly_classification" if self.task_type == TaskType.ANOMALY_CLASSIFICATION else "anomaly_segmentation" + ) + selected_class = ( + AnomalyClassification if self.task_type == TaskType.ANOMALY_CLASSIFICATION else AnomalySegmentation + ) + parameters["type_of_model"] = task_type + parameters["converter_type"] = task_type.upper() parameters["model_parameters"] = self._get_openvino_configuration() name_of_package = "demo_package" with tempfile.TemporaryDirectory() as tempdir: copyfile(os.path.join(work_dir, "setup.py"), os.path.join(tempdir, "setup.py")) copyfile(os.path.join(work_dir, "requirements.txt"), os.path.join(tempdir, "requirements.txt")) - set_proper_git_commit_hash(os.path.join(tempdir, "requirements.txt")) copytree(os.path.join(work_dir, name_of_package), os.path.join(tempdir, name_of_package)) config_path = os.path.join(tempdir, name_of_package, "config.json") with open(config_path, "w", encoding="utf-8") as file: json.dump(parameters, file, ensure_ascii=False, indent=4) - copyfile(inspect.getfile(AnomalyClassification), os.path.join(tempdir, name_of_package, "model.py")) + copyfile(inspect.getfile(selected_class), os.path.join(tempdir, name_of_package, "model.py")) + copyfile(inspect.getfile(AnomalyBase), os.path.join(tempdir, name_of_package, "base.py")) # create wheel package subprocess.run( diff --git a/external/anomaly/anomaly_classification/task.py b/external/anomaly/ote_anomalib/task.py similarity index 85% rename from external/anomaly/anomaly_classification/task.py rename to external/anomaly/ote_anomalib/task.py index 9b2554554d9..42567c3a7bd 100644 --- a/external/anomaly/anomaly_classification/task.py +++ b/external/anomaly/ote_anomalib/task.py @@ -24,22 +24,23 @@ from typing import Optional, Union import torch -from anomalib.core.callbacks import MinMaxNormalizationCallback -from anomalib.core.model import AnomalyModule -from anomalib.models import get_model +from anomalib.models import AnomalyModule, get_model +from anomalib.utils.callbacks import MinMaxNormalizationCallback from omegaconf import DictConfig, ListConfig -from ote_anomalib.callbacks import InferenceCallback, ProgressCallback -from ote_anomalib.config import get_anomalib_config +from ote_anomalib.callbacks import AnomalyInferenceCallback, ProgressCallback +from ote_anomalib.configs import get_anomalib_config from ote_anomalib.data import OTEAnomalyDataModule from ote_anomalib.logging import get_logger from ote_sdk.entities.datasets import DatasetEntity from ote_sdk.entities.inference_parameters import InferenceParameters from ote_sdk.entities.metrics import Performance, ScoreMetric from ote_sdk.entities.model import ModelEntity, ModelPrecision, ModelOptimizationType +from ote_sdk.entities.model_template import TaskType from ote_sdk.entities.resultset import ResultSetEntity from ote_sdk.entities.task_environment import TaskEnvironment from ote_sdk.entities.train_parameters import TrainParameters from ote_sdk.serialization.label_mapper import label_schema_to_bytes +from ote_sdk.usecases.evaluation.averaging import MetricAverageMethod from ote_sdk.usecases.evaluation.metrics_helper import MetricsHelper from ote_sdk.usecases.tasks.interfaces.evaluate_interface import IEvaluationTask from ote_sdk.usecases.tasks.interfaces.export_interface import ExportType, IExportTask @@ -51,9 +52,10 @@ logger = get_logger(__name__) -class AnomalyClassificationTask(ITrainingTask, IInferenceTask, IEvaluationTask, IExportTask, IUnload): - """Base Anomaly Classification Task.""" +class BaseAnomalyTask(ITrainingTask, IInferenceTask, IEvaluationTask, IExportTask, IUnload): + """Base Anomaly Task.""" + # pylint: disable=too-many-instance-attributes def __init__(self, task_environment: TaskEnvironment) -> None: """Train, Infer, Export, Optimize and Deploy an Anomaly Classification Task. @@ -63,6 +65,7 @@ def __init__(self, task_environment: TaskEnvironment) -> None: torch.backends.cudnn.enabled = True logger.info("Initializing the task environment.") self.task_environment = task_environment + self.task_type = task_environment.model_template.task_type self.model_name = task_environment.model_template.name self.labels = task_environment.get_labels() @@ -82,8 +85,16 @@ def get_config(self) -> Union[DictConfig, ListConfig]: """ hyper_parameters = self.task_environment.get_hyper_parameters() config = get_anomalib_config(task_name=self.model_name, ote_config=hyper_parameters) - config.dataset.task = "classification" config.project.path = self.project_path + + # set task type + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + config.dataset.task = "classification" + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + config.dataset.task = "segmentation" + else: + raise ValueError(f"Unknown task type: {self.task_type}") + return config def load_model(self, ote_model: Optional[ModelEntity]) -> AnomalyModule: @@ -138,7 +149,7 @@ def train( config = self.get_config() logger.info("Training Configs '%s'", config) - datamodule = OTEAnomalyDataModule(config=config, dataset=dataset) + datamodule = OTEAnomalyDataModule(config=config, dataset=dataset, task_type=self.task_type) callbacks = [ProgressCallback(parameters=train_parameters), MinMaxNormalizationCallback()] self.trainer = Trainer(**config.trainer, logger=False, callbacks=callbacks) @@ -196,13 +207,13 @@ def infer(self, dataset: DatasetEntity, inference_parameters: InferenceParameter """ logger.info("Performing inference on the validation set using the base torch model.") config = self.get_config() - datamodule = OTEAnomalyDataModule(config=config, dataset=dataset) + datamodule = OTEAnomalyDataModule(config=config, dataset=dataset, task_type=self.task_type) logger.info("Inference Configs '%s'", config) # Callbacks. progress = ProgressCallback(parameters=inference_parameters) - inference = InferenceCallback(dataset, self.labels) + inference = AnomalyInferenceCallback(dataset, self.labels, self.task_type) normalize = MinMaxNormalizationCallback() callbacks = [progress, normalize, inference] @@ -216,24 +227,19 @@ def evaluate(self, output_resultset: ResultSetEntity, evaluation_metric: Optiona Args: output_resultset (ResultSetEntity): Result Set from which the performance is evaluated. evaluation_metric (Optional[str], optional): Evaluation metric. Defaults to None. Instead, - f-measure is used by default. + metric is chosen depending on the task type. """ - metric = MetricsHelper.compute_f_measure(output_resultset) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + metric = MetricsHelper.compute_f_measure(output_resultset) + elif self.task_type == TaskType.ANOMALY_SEGMENTATION: + metric = MetricsHelper.compute_dice_averaged_over_pixels(output_resultset, MetricAverageMethod.MICRO) + else: + raise ValueError(f"Unknown task type: {self.task_type}") output_resultset.performance = metric.get_performance() - accuracy = MetricsHelper.compute_accuracy(output_resultset).get_performance() - output_resultset.performance.dashboard_metrics.extend(accuracy.dashboard_metrics) - - # NOTE: This is for debugging purpose. - for i, _ in enumerate(output_resultset.ground_truth_dataset): - logger.info( - "True vs Pred: %s %s - %3.2f", - output_resultset.ground_truth_dataset[i].annotation_scene.annotations[0].get_labels()[0].name, - output_resultset.prediction_dataset[i].annotation_scene.annotations[0].get_labels()[0].name, - output_resultset.prediction_dataset[i].annotation_scene.annotations[0].get_labels()[0].probability, - ) - logger.info("%s performance of the base torch model: %3.2f", metric.f_measure.name, metric.f_measure.value) - logger.info("%s : %3.2f", accuracy.score.name, accuracy.score.value) + if self.task_type == TaskType.ANOMALY_CLASSIFICATION: + accuracy = MetricsHelper.compute_accuracy(output_resultset).get_performance() + output_resultset.performance.dashboard_metrics.extend(accuracy.dashboard_metrics) def export(self, export_type: ExportType, output_model: ModelEntity) -> None: output_model.optimization_type = ModelOptimizationType.MO @@ -271,6 +277,7 @@ def export(self, export_type: ExportType, output_model: ModelEntity) -> None: def _set_metadata(self, output_model: ModelEntity): output_model.set_data("image_threshold", self.model.image_threshold.value.cpu().numpy().tobytes()) + output_model.set_data("pixel_threshold", self.model.pixel_threshold.value.cpu().numpy().tobytes()) output_model.set_data("min", self.model.min_max.min.cpu().numpy().tobytes()) output_model.set_data("max", self.model.min_max.max.cpu().numpy().tobytes()) diff --git a/external/anomaly/anomaly_classification/tools/sample.py b/external/anomaly/ote_anomalib/tools/sample.py similarity index 95% rename from external/anomaly/anomaly_classification/tools/sample.py rename to external/anomaly/ote_anomalib/tools/sample.py index f823be60803..0769d90f0a7 100644 --- a/external/anomaly/anomaly_classification/tools/sample.py +++ b/external/anomaly/ote_anomalib/tools/sample.py @@ -24,10 +24,7 @@ from argparse import Namespace from typing import Any, cast -from anomaly_classification import ( - AnomalyClassificationTask, - OpenVINOAnomalyClassificationTask, -) +from ote_anomalib import BaseAnomalyTask, OpenVINOAnomalyTask from ote_anomalib.data.mvtec import OteMvtecDataset from ote_anomalib.logging import get_logger from ote_sdk.configuration.helper import create as create_hyper_parameters @@ -79,19 +76,21 @@ def __init__(self, dataset_path: str, seed: int, model_template_path: str) -> No >>> task.export() Performance(score: 0.9756097560975608, dashboard: (1 metric groups)) """ - logger.info("Loading MVTec dataset.") - self.dataset = OteMvtecDataset(path=dataset_path, seed=seed).generate() logger.info("Loading the model template.") self.model_template = parse_model_template(model_template_path) + logger.info("Loading MVTec dataset.") + self.task_type = self.model_template.task_type + self.dataset = OteMvtecDataset(path=dataset_path, seed=seed, task_type=self.task_type).generate() + logger.info("Creating the task-environment.") self.task_environment = self.create_task_environment() logger.info("Creating the base Torch and OpenVINO tasks.") self.torch_task = self.create_task(task="base") - self.torch_task = cast(AnomalyClassificationTask, self.torch_task) - self.openvino_task: OpenVINOAnomalyClassificationTask + self.torch_task = cast(BaseAnomalyTask, self.torch_task) + self.openvino_task: OpenVINOAnomalyTask def create_task_environment(self) -> TaskEnvironment: """Create task environment.""" @@ -129,7 +128,7 @@ def create_task(self, task: str) -> Any: module = importlib.import_module(module_name) return getattr(module, class_name)(task_environment=self.task_environment) - def train(self) -> None: + def train(self) -> ModelEntity: """Train the base Torch model.""" logger.info("Training the model.") output_model = ModelEntity( @@ -147,6 +146,7 @@ def train(self) -> None: logger.info("Evaluating the base torch model on the validation set.") self.evaluate(self.torch_task, result_set) + return output_model def infer(self, task: IInferenceTask, output_model: ModelEntity) -> ResultSetEntity: """Get the predictions using the base Torch or OpenVINO tasks and models. @@ -183,7 +183,7 @@ def evaluate(task: IEvaluationTask, result_set: ResultSetEntity) -> None: task.evaluate(result_set) logger.info(str(result_set.performance)) - def export(self) -> None: + def export(self) -> ModelEntity: """Export the model via openvino.""" logger.info("Exporting the model.") exported_model = ModelEntity( @@ -196,13 +196,14 @@ def export(self) -> None: logger.info("Creating the OpenVINO Task.") self.openvino_task = self.create_task(task="openvino") - self.openvino_task = cast(OpenVINOAnomalyClassificationTask, self.openvino_task) + self.openvino_task = cast(OpenVINOAnomalyTask, self.openvino_task) logger.info("Inferring the exported model on the validation set.") result_set = self.infer(task=self.openvino_task, output_model=exported_model) logger.info("Evaluating the exported model on the validation set.") self.evaluate(task=self.openvino_task, result_set=result_set) + return exported_model def optimize(self) -> None: """Optimize the model via POT.""" diff --git a/external/anomaly/requirements.txt b/external/anomaly/requirements.txt index 1a3d6b30f3d..990df5b3f7e 100644 --- a/external/anomaly/requirements.txt +++ b/external/anomaly/requirements.txt @@ -1,5 +1,5 @@ -anomalib @ git+https://github.com/openvinotoolkit/anomalib.git@2bae059c65630e5288837915222a07e9cdbad658 +anomalib @ git+https://github.com/openvinotoolkit/anomalib.git@5f3ee2725d97af8a0a7865b2fcac7280140bfc08 openmodelzoo-modelapi @ git+https://github.com/openvinotoolkit/open_model_zoo/@releases/2021/SCMVP#egg=openmodelzoo-modelapi&subdirectory=demos/common/python -openvino==2021.4.2 -openvino-dev==2021.4.2 +openvino==2022.1.0.dev20220302 +openvino-dev==2022.1.0.dev20220302 onnx==1.10.1 diff --git a/external/anomaly/setup.py b/external/anomaly/setup.py index f33b414e77c..71c7245f9b8 100644 --- a/external/anomaly/setup.py +++ b/external/anomaly/setup.py @@ -35,15 +35,21 @@ def get_requirements() -> List[str]: setup( - name="anomaly_classification", + name="anomaly tasks", version="ote-alpha", packages=find_packages( - include=["anomaly_classification", "anomaly_classification.*", "ote_anomalib", "ote_anomalib.*"] + include=[ + "ote_anomalib", + "ote_anomalib.*", + "anomaly_classification", + "anomaly_classification.*", + "anomaly_segmentation", + "anomaly_segmentation.*", + ] ), url="", license="license='Apache License 2.0'", install_requires=get_requirements(), author="Intel", - description="anomaly classification - " - "OpenVINO Training Extension for Anomaly Classification using anomalib library", + description="anomaly tasks" "OpenVINO Training Extension for Anomaly Classification using anomalib library", ) diff --git a/external/anomaly/tests/helpers/dummy_dataset.py b/external/anomaly/tests/helpers/dummy_dataset.py index 3b70cc82c59..3b0a7857aae 100644 --- a/external/anomaly/tests/helpers/dummy_dataset.py +++ b/external/anomaly/tests/helpers/dummy_dataset.py @@ -53,7 +53,7 @@ def generate_random_anomaly_image( """ image: np.ndarray = np.full((image_height, image_width, 3), 255, dtype=np.uint8) - input_region = [0, 0, image_height, image_width] + input_region = [0, 0, image_width - 1, image_height - 1] for shape in shapes: shape_image = random_shapes(input_region, (image_height, image_width), max_shapes=max_shapes, shape=shape) diff --git a/external/anomaly/tests/helpers/train.py b/external/anomaly/tests/helpers/train.py deleted file mode 100644 index 7b8f37861b4..00000000000 --- a/external/anomaly/tests/helpers/train.py +++ /dev/null @@ -1,230 +0,0 @@ -""" -Anomaly Classification Training Helper -""" - -# Copyright (C) 2021 Intel Corporation -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, -# software distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions -# and limitations under the License. - -import importlib -import logging -import os -import time -from typing import Union - -from anomaly_classification import ( - AnomalyClassificationTask, - OpenVINOAnomalyClassificationTask, -) -from ote_anomalib.data.mvtec import OteMvtecDataset -from ote_sdk.configuration.helper import create -from ote_sdk.entities.inference_parameters import InferenceParameters -from ote_sdk.entities.label_schema import LabelSchemaEntity -from ote_sdk.entities.model import ModelEntity -from ote_sdk.entities.model_template import parse_model_template -from ote_sdk.entities.optimization_parameters import OptimizationParameters -from ote_sdk.entities.resultset import ResultSetEntity -from ote_sdk.entities.subset import Subset -from ote_sdk.entities.task_environment import TaskEnvironment -from ote_sdk.entities.train_parameters import TrainParameters -from ote_sdk.usecases.tasks.interfaces.export_interface import ExportType -from ote_sdk.usecases.tasks.interfaces.optimization_interface import OptimizationType - -logger = logging.getLogger(__name__) - - -class OTEAnomalyTrainer: - """ - OTE Trainer is a helper class that creates the required components - to train, infer and export a model. - - Args: - model_template_path (str, optional): path to model template. - Defaults to "../../anomaly_classification/configs/padim/template.yaml". - """ - - def __init__( - self, - model_template_path: str = "../../anomaly_classification/configs/padim/template.yaml", - dataset_path: str = "./datasets/MVTec", - category: str = "bottle", - ): - dataset_path = os.path.join(dataset_path, category) - self.dataset_generator = OteMvtecDataset(path=dataset_path) - self.dataset = self.dataset_generator.generate() - - self.model_template_path = model_template_path - self.model_template = parse_model_template(model_template_path) - self.task_environment = self.create_task_environment() - self.base_task = self.create_task() - self.openvino_task: OpenVINOAnomalyClassificationTask - - self.output_model = ModelEntity( - train_dataset=self.dataset, - configuration=self.task_environment.get_model_configuration(), - ) - - self.was_training_run_before: bool = False - self.was_export_run_before: bool = False - self.stored_exception_training: Exception - self.stored_exception_export: Exception - - def create_task_environment(self) -> TaskEnvironment: - """ - Create Task Environment - - Returns: - TaskEnvironment: Task Environment - """ - hyper_parameters = create(input_config=self.model_template.hyper_parameters.data) - - labels = [ - self.dataset_generator.normal_label, - self.dataset_generator.abnormal_label, - ] - label_schema = LabelSchemaEntity.from_labels(labels) - - task_environment = TaskEnvironment( - model_template=self.model_template, - model=None, - hyper_parameters=hyper_parameters, - label_schema=label_schema, - ) - - return task_environment - - def create_task(self) -> AnomalyClassificationTask: - """ - Create Anomaly Training Task - - Returns: - AnomalyClassificationTask: anomaly training task. - """ - path = self.model_template.entrypoints.base - module_name, class_name = path.rsplit(".", 1) - module = importlib.import_module(module_name) - return getattr(module, class_name)(task_environment=self.task_environment) - - def train(self): - """ - Train OTE Model - """ - - # Check if there is a previous train cycle, and if it's successful. - if self.was_training_run_before and self.stored_exception_training: - logger.warning( - "In function run_ote_training_once: found that previous call of the function " - "caused exception -- re-raising it" - ) - raise self.stored_exception_training - - # Train the Model. - if not self.was_training_run_before: - try: - self.base_task.train( - dataset=self.dataset, - output_model=self.output_model, - train_parameters=TrainParameters(), - ) - - except Exception as exception: - self.stored_exception_training = exception - raise exception - - self.was_training_run_before = True - - # Get the training performance of `output_model`. - performance = self.output_model.performance - if performance is None: - raise ValueError("Model does not have a saved performance.") - - logger.debug( - "Training performance: %s, %3.2f", - performance.score.name, - performance.score.value, - ) - - def validate( - self, - task: Union[AnomalyClassificationTask, OpenVINOAnomalyClassificationTask], - subset=Subset.TESTING, - optimize: bool = False, - ) -> ResultSetEntity: - """ - Run one epoch on the inference dataset using Base or OpenVino Inferencer. - - Args: - task (Union[AnomalyClassificationTask, OpenVINOAnomalyClassificationTask]): Base or OpenVino inferencer - subset (Subset, optional): Validation or Test split. Defaults to Subset.TESTING. - optimize (bool, optional): Boolean to optimize the model via POT. - - Returns: - ResultSetEntity: [description] - """ - - inference_dataset = self.dataset.get_subset(subset) - inference_parameters = InferenceParameters(is_evaluation=True) - - predicted_inference_dataset = task.infer( - dataset=inference_dataset.with_empty_annotations(), - inference_parameters=inference_parameters, - ) - - result_set = ResultSetEntity( - model=self.output_model, - ground_truth_dataset=inference_dataset, - prediction_dataset=predicted_inference_dataset, - ) - - if optimize: - if isinstance(task, AnomalyClassificationTask): - raise ValueError("Base task cannot perform optimization") - - self.openvino_task.optimize( - optimization_type=OptimizationType.POT, - dataset=inference_dataset, - output_model=self.task_environment.model, - optimization_parameters=OptimizationParameters(), - ) - - task.evaluate(output_resultset=result_set) - return result_set - - def cancel_training(self): - """ - Cancel Training - """ - time.sleep(1) - self.base_task.cancel_training() - - def export(self): - """ - Export the OpenVino Model - """ - self.base_task.export(ExportType.OPENVINO, self.output_model) - # assign the converted OpenVINO model to the current task environment model - self.task_environment.model = self.output_model - self.openvino_task = OpenVINOAnomalyClassificationTask(task_environment=self.task_environment) - - def deploy(self): - """ - Generate Exportable code for model - """ - try: - self.output_model.get_data("openvino.bin") - except KeyError as error: - raise KeyError( - "Could not get `openvino.bin` from model. Make sure that the model is exported to OpenVINO first" - ) from error - - self.openvino_task.deploy(self.output_model) diff --git a/external/anomaly/tests/test_configurable_parameters.py b/external/anomaly/tests/test_configurable_parameters.py index e4f5de913cf..281f2fb8815 100644 --- a/external/anomaly/tests/test_configurable_parameters.py +++ b/external/anomaly/tests/test_configurable_parameters.py @@ -20,16 +20,19 @@ import os import pytest -from anomaly_classification.configs.padim import PadimConfig -from anomaly_classification.configs.stfpm import STFPMConfig -from ote_anomalib.config import get_anomalib_config +from anomaly_classification.configs.padim import PadimAnomalyClassificationConfig +from anomaly_classification.configs.stfpm import STFPMAnomalyClassificationConfig +from ote_anomalib.configs import get_anomalib_config from ote_sdk.configuration.helper import convert, create from tests.helpers.config import get_config_and_task_name logger = logging.getLogger(__name__) -@pytest.mark.parametrize(["model_name", "configurable_parameters"], [("padim", PadimConfig), ("stfpm", STFPMConfig)]) +@pytest.mark.parametrize( + ["model_name", "configurable_parameters"], + [("padim", PadimAnomalyClassificationConfig), ("stfpm", STFPMAnomalyClassificationConfig)], +) def test_configuration_yaml(configurable_parameters, model_name): # assert that we can parse the template.yaml template_file_path = os.path.join("anomaly_classification", "configs", model_name, "template.yaml") diff --git a/external/anomaly/tests/test_ote_anomaly_classification.py b/external/anomaly/tests/test_ote_task.py similarity index 64% rename from external/anomaly/tests/test_ote_anomaly_classification.py rename to external/anomaly/tests/test_ote_task.py index 214dda444e3..5f8366b0d18 100644 --- a/external/anomaly/tests/test_ote_anomaly_classification.py +++ b/external/anomaly/tests/test_ote_task.py @@ -21,24 +21,30 @@ import numpy as np import pytest -from ote_anomalib.config import get_anomalib_config +from ote_anomalib.configs import get_anomalib_config +from ote_anomalib.tools.sample import OteAnomalyTask from tests.helpers.config import get_config_and_task_name from tests.helpers.dummy_dataset import TestDataset -from tests.helpers.train import OTEAnomalyTrainer logger = logging.getLogger(__name__) @pytest.mark.parametrize( ["task_path", "template_path"], - [("anomaly_classification", "padim"), ("anomaly_classification", "stfpm")], + [ + ("anomaly_classification", "padim"), + ("anomaly_classification", "stfpm"), + ("anomaly_segmentation", "padim"), + ("anomaly_segmentation", "stfpm"), + ], ) class TestAnomalyClassification: """ Anomaly Classification Task Tests. """ - _trainer: OTEAnomalyTrainer + # _trainer: OTEAnomalyTrainer + _trainer: OteAnomalyTask @staticmethod def test_ote_config(task_path, template_path): @@ -65,55 +71,60 @@ def test_ote_train_export_and_optimize( E2E Train-Export Should Yield Similar Inference Results """ # Train the model - self._trainer = OTEAnomalyTrainer( - model_template_path=f"{task_path}/configs/{template_path}/template.yaml", + dataset_path = os.path.join(dataset_path, category) + self._trainer = OteAnomalyTask( dataset_path=dataset_path, - category=category, + model_template_path=f"{task_path}/configs/{template_path}/template.yaml", + seed=0, ) - self._trainer.train() - base_results = self._trainer.validate(task=self._trainer.base_task) - assert base_results.performance.score.value > 0.5 + output_model = self._trainer.train() + + base_results = self._trainer.infer(task=self._trainer.torch_task, output_model=output_model) + self._trainer.evaluate(task=self._trainer.torch_task, result_set=base_results) + + if task_path == "anomaly_classification": # skip this check for anomaly segmentation until we switch metrics + assert base_results.performance.score.value > 0.5 # Convert the model to OpenVINO self._trainer.export() - openvino_results = self._trainer.validate(task=self._trainer.openvino_task) - - base_probability_scores = [ - base_results.prediction_dataset[i].annotation_scene.annotations[0].get_labels()[0].probability - for i in range(len(base_results.prediction_dataset)) - ] - openvino_probability_scores = [ - openvino_results.prediction_dataset[i].annotation_scene.annotations[0].get_labels()[0].probability - for i in range(len(openvino_results.prediction_dataset)) - ] + openvino_results = self._trainer.infer(task=self._trainer.openvino_task, output_model=output_model) + self._trainer.evaluate(task=self._trainer.openvino_task, result_set=openvino_results) - assert np.allclose(base_probability_scores, openvino_probability_scores, rtol=0.05) + assert np.allclose(base_results.performance.score.value, openvino_results.performance.score.value, atol=0.1) @TestDataset(num_train=200, num_test=10, dataset_path="./datasets/MVTec", use_mvtec=False) def test_ote_deploy(self, task_path, template_path, dataset_path="./datasets/MVTec", category="bottle"): """ E2E Test generation of exportable code. """ - self._trainer = OTEAnomalyTrainer( + dataset_path = os.path.join(dataset_path, category) + self._trainer = OteAnomalyTask( model_template_path=f"{task_path}/configs/{template_path}/template.yaml", dataset_path=dataset_path, - category=category, + seed=0, ) # Train is called as we need threshold self._trainer.train() # Convert the model to OpenVINO - self._trainer.export() + output_model = self._trainer.export() # generate exportable code - self._trainer.deploy() + try: + output_model.get_data("openvino.bin") + except KeyError as error: + raise KeyError( + "Could not get `openvino.bin` from model. Make sure that the model is exported to OpenVINO first" + ) from error + + self._trainer.openvino_task.deploy(output_model) # write zip file from the model weights with tempfile.TemporaryDirectory() as tempdir: zipfile = os.path.join(tempdir, "openvino.zip") with open(zipfile, "wb") as output_arch: - output_arch.write(self._trainer.output_model.exportable_code) + output_arch.write(output_model.exportable_code) # check if size of zip is greater than 0 bytes assert os.path.getsize(zipfile) > 0 diff --git a/external/anomaly/tests/test_ote_training.py b/external/anomaly/tests/test_ote_training.py index 19d2d7a59fa..2158bbc5d6d 100644 --- a/external/anomaly/tests/test_ote_training.py +++ b/external/anomaly/tests/test_ote_training.py @@ -99,9 +99,8 @@ def _create_anomaly_classification_dataset_and_labels_schema(dataset_params, dat items.extend(OteMvtecDataset(path=dataset_params.dataset_path, seed=0).generate()) else: for category in category_list: - if "vivo" not in category: - logger.debug(f'Creating dataset for {category}') - items.extend(OteMvtecDataset(path=category, seed=0).generate()) + logger.debug(f'Creating dataset for {category}') + items.extend(OteMvtecDataset(path=category, seed=0).generate()) dataset = DatasetEntity(items=items) labels = dataset.get_labels() labels_schema = LabelSchemaEntity.from_labels(labels) diff --git a/external/deep-object-reid b/external/deep-object-reid index 1abd68b027b..d5a9f2cb2b4 160000 --- a/external/deep-object-reid +++ b/external/deep-object-reid @@ -1 +1 @@ -Subproject commit 1abd68b027b94014d08e9ea18c2cfbb0824969d9 +Subproject commit d5a9f2cb2b414c1c5aa822faa22ab8b3ab83eb6b diff --git a/external/mmdetection b/external/mmdetection index ad922124f7a..5e637be7b98 160000 --- a/external/mmdetection +++ b/external/mmdetection @@ -1 +1 @@ -Subproject commit ad922124f7a727553c75b83f5a98e201e96f905c +Subproject commit 5e637be7b984bc056e9a5c1a37d34ffb423d1dfa diff --git a/external/mmsegmentation b/external/mmsegmentation index ee2a6aba0c2..46c6f78a521 160000 --- a/external/mmsegmentation +++ b/external/mmsegmentation @@ -1 +1 @@ -Subproject commit ee2a6aba0c2582d3d3b7e244aeda350737545766 +Subproject commit 46c6f78a521859758592263d0c0b19fcc9824762 diff --git a/ote_cli/ote_cli/datasets/__init__.py b/ote_cli/ote_cli/datasets/__init__.py index 4f7844dbcff..9eb426971b9 100644 --- a/ote_cli/ote_cli/datasets/__init__.py +++ b/ote_cli/ote_cli/datasets/__init__.py @@ -19,19 +19,24 @@ from ote_sdk.entities.model_template import TaskType +# pylint: disable=too-many-return-statements def get_dataset_class(task_type): """ Returns a dataset class by task type. Args: - task_type: A task type such as ANOMALY_CLASSIFICATION, CLASSIFICATION, INSTANCE_SEGMENTATION, DETECTION, - CLASSIFICATION, ROTATED_DETECTION, SEGMENTATION. + task_type: A task type such as ANOMALY_CLASSIFICATION, ANOMALY_SEGMENTATION, CLASSIFICATION, + INSTANCE_SEGMENTATION, DETECTION, CLASSIFICATION, ROTATED_DETECTION, SEGMENTATION. """ if task_type == TaskType.ANOMALY_CLASSIFICATION: from .anomaly.dataset import AnomalyClassificationDataset return AnomalyClassificationDataset + if task_type == TaskType.ANOMALY_SEGMENTATION: + from .anomaly.dataset import AnomalySegmentationDataset + + return AnomalySegmentationDataset if task_type == TaskType.CLASSIFICATION: from .image_classification.dataset import ImageClassificationDataset diff --git a/ote_cli/ote_cli/datasets/anomaly/dataset.py b/ote_cli/ote_cli/datasets/anomaly/dataset.py index 5dc4800213d..b92153c0cf7 100644 --- a/ote_cli/ote_cli/datasets/anomaly/dataset.py +++ b/ote_cli/ote_cli/datasets/anomaly/dataset.py @@ -13,10 +13,12 @@ # See the License for the specific language governing permissions # and limitations under the License. +import warnings from pathlib import Path from typing import Dict, List, Optional import pandas as pd +from bson import ObjectId from ote_sdk.entities.annotation import ( Annotation, AnnotationSceneEntity, @@ -28,6 +30,7 @@ from ote_sdk.entities.image import Image from ote_sdk.entities.label import Domain, LabelEntity from ote_sdk.entities.scored_label import ScoredLabel +from ote_sdk.entities.shapes.polygon import Point, Polygon from ote_sdk.entities.shapes.rectangle import Rectangle from ote_sdk.entities.subset import Subset @@ -37,14 +40,14 @@ class AnomalyClassificationDataset(DatasetEntity): Example: >>> train_subset = { - "ann_file": "data/anomaly/train.json", + "ann_file": "data/anomaly/classification/train.json", "data_root": "data/anomaly/shapes", } - >>> val_subset = {"ann_file": "data/anomaly/val.json", "data_root": "data/anomaly/shapes"} + >>> val_subset = {"ann_file": "data/anomaly/classification/val.json", "data_root": "data/anomaly/shapes"} >>> training_dataset = AnomalyClassificationDataset( train_subset=train_subset, val_subset=val_subset ) - >>> test_subset = {"ann_file": "data/anomaly/test.json", "data_root": "data/anomaly/shapes"} + >>> test_subset = {"ann_file": "data/anomaly/classification/test.json", "data_root": "data/anomaly/shapes"} >>> testing_dataset = AnomalyClassificationDataset(test_subset=test_subset) Args: @@ -68,7 +71,10 @@ def __init__( id=ID(0), name="Normal", domain=Domain.ANOMALY_CLASSIFICATION ) self.abnormal_label = LabelEntity( - id=ID(1), name="Anomalous", domain=Domain.ANOMALY_CLASSIFICATION + id=ID(1), + name="Anomalous", + domain=Domain.ANOMALY_CLASSIFICATION, + is_anomalous=True, ) if train_subset is not None: @@ -147,3 +153,149 @@ def get_dataset_items( dataset_items.append(dataset_item) return dataset_items + + +class AnomalySegmentationDataset(DatasetEntity): + """Dataloader for Anomaly Segmentation Task. + + Example: + >>> train_subset = { + "ann_file": "data/anomaly/segmentation/train.json", + "data_root": "data/anomaly/shapes", + } + >>> val_subset = {"ann_file": "data/anomaly/segmentation/val.json", "data_root": "data/anomaly/shapes"} + >>> training_dataset = AnomalySegmentationDataset( + train_subset=train_subset, val_subset=val_subset + ) + >>> test_subset = {"ann_file": "data/anomaly/segmentation/test.json", "data_root": "data/anomaly/shapes"} + >>> testing_dataset = AnomalySegmentationDataset(test_subset=test_subset) + + Args: + train_subset (Optional[Dict[str, str]], optional): Path to annotation + and dataset used for training. Defaults to None. + val_subset (Optional[Dict[str, str]], optional): Path to annotation + and dataset used for validation. Defaults to None. + test_subset (Optional[Dict[str, str]], optional): Path to annotation + and dataset used for testing. Defaults to None. + """ + + def __init__( + self, + train_subset: Optional[Dict[str, str]] = None, + val_subset: Optional[Dict[str, str]] = None, + test_subset: Optional[Dict[str, str]] = None, + ): + + items: List[DatasetItemEntity] = [] + self.normal_label = LabelEntity( + id=ID(0), name="Normal", domain=Domain.ANOMALY_SEGMENTATION + ) + self.abnormal_label = LabelEntity( + id=ID(1), + name="Anomalous", + domain=Domain.ANOMALY_SEGMENTATION, + is_anomalous=True, + ) + + if train_subset is not None: + train_ann_file = Path(train_subset["ann_file"]) + train_data_root = Path(train_subset["data_root"]) + items.extend( + self.get_dataset_items( + ann_file_path=train_ann_file, + data_root_dir=train_data_root, + subset=Subset.TRAINING, + ) + ) + + if val_subset is not None: + val_ann_file = Path(val_subset["ann_file"]) + val_data_root = Path(val_subset["data_root"]) + items.extend( + self.get_dataset_items( + ann_file_path=val_ann_file, + data_root_dir=val_data_root, + subset=Subset.VALIDATION, + ) + ) + + if test_subset is not None: + test_ann_file = Path(test_subset["ann_file"]) + test_data_root = Path(test_subset["data_root"]) + items.extend( + self.get_dataset_items( + ann_file_path=test_ann_file, + data_root_dir=test_data_root, + subset=Subset.TESTING, + ) + ) + + super().__init__(items=items) + + def get_dataset_items( + self, ann_file_path: Path, data_root_dir: Path, subset: Subset + ) -> List[DatasetItemEntity]: + """Loads dataset based on the image path in annotation file. + + Args: + ann_file_path (Path): Path to json containing the annotations. + For example of annotation look at `data/anomaly/[train, test,val].json. + data_root_dir (Path): Path to folder containing images. + subset (Subset): Subset of the dataset. + + Returns: + List[DatasetItemEntity]: List containing subset dataset. + """ + # read annotation file + samples = pd.read_json(ann_file_path) + + dataset_items = [] + for _, sample in samples.iterrows(): + # Create image + # convert path to str as PosixPath is not supported by Image + image = Image(file_path=str(data_root_dir / sample.image_path)) + # Create annotation + label: LabelEntity = ( + self.normal_label if sample.label == "good" else self.abnormal_label + ) + annotations = [] + if isinstance(sample.masks, list) and len(sample.masks) > 0: + for contour in sample.masks: + points = [Point(x, y) for x, y in contour] + polygon = Polygon(points=points) + if polygon.get_area() > 0: + # Contour is a closed polygon with area > 0 + annotations.append( + Annotation( + shape=polygon, + labels=[ScoredLabel(label, 1.0)], + id=ID(ObjectId()), + ) + ) + else: + # Contour is a closed polygon with area == 0 + warnings.warn( + "The geometry of the segmentation map you are converting " + "is not fully supported. Polygons with a area of zero " + "will be removed.", + UserWarning, + ) + else: + annotations.append( + Annotation( + Rectangle.generate_full_box(), + labels=[ScoredLabel(label=self.normal_label, probability=1.0)], + ) + ) + annotation_scene = AnnotationSceneEntity( + annotations=annotations, kind=AnnotationSceneKind.ANNOTATION + ) + + # Add to dataset items + dataset_items.append( + DatasetItemEntity( + media=image, annotation_scene=annotation_scene, subset=subset + ) + ) + + return dataset_items diff --git a/ote_cli/ote_cli/tools/utils/demo/visualization.py b/ote_cli/ote_cli/tools/utils/demo/visualization.py index 680c6ec678c..03e9a71184a 100644 --- a/ote_cli/ote_cli/tools/utils/demo/visualization.py +++ b/ote_cli/ote_cli/tools/utils/demo/visualization.py @@ -155,7 +155,7 @@ def draw_predictions(task_type, predictions, frame, fit_to_size): frame = put_labels(frame, predictions) elif task_type in {TaskType.INSTANCE_SEGMENTATION, TaskType.ROTATED_DETECTION}: frame = draw_masks(frame, predictions, put_object_count=True) - elif task_type == TaskType.SEGMENTATION: + elif task_type in {TaskType.SEGMENTATION, TaskType.ANOMALY_SEGMENTATION}: frame = draw_masks(frame, predictions, put_object_count=False) else: raise ValueError(f"Unknown task type: {task_type}") diff --git a/ote_cli/ote_cli/utils/io.py b/ote_cli/ote_cli/utils/io.py index af9cdfb385c..c6709e19ee1 100644 --- a/ote_cli/ote_cli/utils/io.py +++ b/ote_cli/ote_cli/utils/io.py @@ -63,7 +63,13 @@ def read_model(model_configuration, path, train_dataset): """ optimization_type = ModelOptimizationType.NONE - model_adapter_keys = ("confidence_threshold", "image_threshold", "min", "max") + model_adapter_keys = ( + "confidence_threshold", + "image_threshold", + "pixel_threshold", + "min", + "max", + ) if path.endswith(".bin") or path.endswith(".xml"): # Openvino IR. @@ -105,7 +111,7 @@ def read_model(model_configuration, path, train_dataset): } config_path = os.path.join(temp_dir, "demo_package", "config.json") - with open(config_path) as f: + with open(config_path, encoding="UTF-8") as f: model_parameters = json.load(f)["model_parameters"] for key in model_adapter_keys: diff --git a/ote_cli/requirements.txt b/ote_cli/requirements.txt index 2ae4cdea345..09af759278e 100644 --- a/ote_cli/requirements.txt +++ b/ote_cli/requirements.txt @@ -5,4 +5,3 @@ nbmake pytest pytest-ordering hpopt@git+https://github.com/openvinotoolkit/hyper_parameter_optimization@v0.1.0 -nncf==2.1.0 \ No newline at end of file diff --git a/ote_sdk/ote_sdk/entities/annotation.py b/ote_sdk/ote_sdk/entities/annotation.py index 5b0027a2ef8..5e929d8dc97 100644 --- a/ote_sdk/ote_sdk/entities/annotation.py +++ b/ote_sdk/ote_sdk/entities/annotation.py @@ -26,7 +26,7 @@ class Annotation(metaclass=abc.ABCMeta): def __init__( self, shape: ShapeEntity, labels: List[ScoredLabel], id: Optional[ID] = None ): - self.__id = ID(ObjectId()) if id is None else id + self.__id_ = ID(ObjectId()) if id is None else id self.__shape = shape self.__labels = labels @@ -35,19 +35,29 @@ def __repr__(self): f"{self.__class__.__name__}(" f"shape={self.shape}, " f"labels={self.get_labels(True)}, " - f"id={self.id})" + f"id={self.id_})" ) @property - def id(self): + def id_(self): """ Returns the id for the annotation """ - return self.__id + return self.__id_ + + @id_.setter + def id_(self, value): + self.__id_ = value + + @property + def id(self): + """DEPRECATED""" + return self.__id_ @id.setter def id(self, value): - self.__id = value + """DEPRECATED""" + self.__id_ = value @property def shape(self): @@ -79,7 +89,9 @@ def get_label_ids(self, include_empty: bool = False) -> Set[ID]: :return: Set of label id's in annotation """ return { - label.id for label in self.__labels if include_empty or (not label.is_empty) + label.id_ + for label in self.__labels + if include_empty or (not label.is_empty) } def append_label(self, label: ScoredLabel): @@ -101,7 +113,7 @@ def set_labels(self, labels: List[ScoredLabel]): def __eq__(self, other): if isinstance(other, Annotation): return ( - self.id == other.id + self.id_ == other.id_ and self.get_labels(True) == other.get_labels(True) and self.shape == other.shape ) @@ -163,7 +175,7 @@ def __init__( self.__kind = kind self.__editor = editor self.__creation_date = now() if creation_date is None else creation_date - self.__id = ID() if id is None else id + self.__id_ = ID() if id is None else id def __repr__(self): return ( @@ -172,19 +184,29 @@ def __repr__(self): f"kind={self.kind}, " f"editor={self.editor_name}, " f"creation_date={self.creation_date}, " - f"id={self.id})" + f"id={self.id_})" ) @property - def id(self): + def id_(self): """ Returns the ID of the AnnotationSceneEntity. """ - return self.__id + return self.__id_ + + @id_.setter + def id_(self, value): + self.__id_ = value + + @property + def id(self): + """DEPRECATED""" + return self.__id_ @id.setter def id(self, value): - self.__id = value + """DEPRECATED""" + self.__id_ = value @property def kind(self): @@ -279,7 +301,7 @@ def get_labels(self, include_empty: bool = False) -> List[LabelEntity]: labels: Dict[str, LabelEntity] = {} for annotation in self.annotations: for label in annotation.get_labels(include_empty): - id_ = label.id + id_ = label.id_ if id_ not in labels: labels[id_] = label.get_label() return list(labels.values()) diff --git a/ote_sdk/ote_sdk/entities/dataset_item.py b/ote_sdk/ote_sdk/entities/dataset_item.py index f700f4bd539..8f9c6a3e375 100644 --- a/ote_sdk/ote_sdk/entities/dataset_item.py +++ b/ote_sdk/ote_sdk/entities/dataset_item.py @@ -9,7 +9,7 @@ import itertools import logging from threading import Lock -from typing import List, Optional, Sequence +from typing import List, Optional, Sequence, Set, Tuple, Union import numpy as np @@ -31,13 +31,14 @@ class DatasetItemEntity(metaclass=abc.ABCMeta): DatasetItemEntity represents an item in the DatasetEntity. It holds a media item, annotation and an ROI. The ROI determines the region of interest for the dataset item, and is described by a shape entity. - Dataset items hold five fundamental properties: + The fundamental properties of a dataset item are: - A 2d media entity (e.g. Image) - A 2d annotation entity for the full resolution media entity - An ROI, describing the region of interest. - The subset it belongs to - Metadata for the media entity (e.g. saliency map or active score) + - A list of labels to ignore .. rubric:: Getting data from dataset item @@ -78,6 +79,9 @@ class DatasetItemEntity(metaclass=abc.ABCMeta): :param roi: Region Of Interest :param metadata: Metadata attached to dataset item :param subset: `Subset` for item. E.g. `Subset.VALIDATION` + :param ignored_labels: Collection of labels that should be ignored in this dataset item. + For instance, in a training scenario, this parameter is used to ignore certain labels within the + existing annotations because their status becomes uncertain following a label schema change. """ # pylint: disable=too-many-arguments @@ -88,6 +92,9 @@ def __init__( roi: Optional[Annotation] = None, metadata: Optional[Sequence[MetadataItemEntity]] = None, subset: Subset = Subset.NONE, + ignored_labels: Optional[ + Union[List[LabelEntity], Tuple[LabelEntity, ...], Set[LabelEntity]] + ] = None, ): self.__media: IMedia2DEntity = media self.__annotation_scene: AnnotationSceneEntity = annotation_scene @@ -107,11 +114,28 @@ def __init__( if metadata is not None: self.__metadata = list(metadata) + self.__ignored_labels: Set[LabelEntity] = ( + set() if ignored_labels is None else set(ignored_labels) + ) + @property def metadata(self) -> Sequence[MetadataItemEntity]: """Provides access to metadata.""" return self.__metadata + @property + def ignored_labels(self) -> Set[LabelEntity]: + """ + Get the IDs of the labels to ignore in this dataset item + """ + return self.__ignored_labels + + @ignored_labels.setter + def ignored_labels( + self, value: Union[List[LabelEntity], Tuple[LabelEntity, ...], Set[LabelEntity]] + ): + self.__ignored_labels = set(value) + def __repr__(self): return ( f"{self.__class__.__name__}(" @@ -372,6 +396,7 @@ def __eq__(self, other): and self.annotation_scene == other.annotation_scene and self.roi == other.roi and self.subset == other.subset + and self.ignored_labels == other.ignored_labels ) return False diff --git a/ote_sdk/ote_sdk/entities/datasets.py b/ote_sdk/ote_sdk/entities/datasets.py index 3fa6914f209..59953cb25ed 100644 --- a/ote_sdk/ote_sdk/entities/datasets.py +++ b/ote_sdk/ote_sdk/entities/datasets.py @@ -277,7 +277,7 @@ def with_empty_annotations( # reset ROI roi = copy.copy(dataset_item.roi) - roi.id = ID(ObjectId()) + roi.id_ = ID(ObjectId()) roi.set_labels([]) new_dataset_item = DatasetItemEntity( diff --git a/ote_sdk/ote_sdk/entities/label.py b/ote_sdk/ote_sdk/entities/label.py index 287737f7302..4ad558d13f7 100644 --- a/ote_sdk/ote_sdk/entities/label.py +++ b/ote_sdk/ote_sdk/entities/label.py @@ -102,7 +102,7 @@ def __init__( self._domain = domain self._is_empty = is_empty self._creation_date = creation_date - self._id = id + self.__id_ = id self.is_anomalous = is_anomalous @property @@ -164,26 +164,36 @@ def creation_date(self) -> datetime.datetime: return self._creation_date @property - def id(self) -> ID: + def id_(self) -> ID: """ Returns the label id. """ - return self._id + return self.__id_ + + @id_.setter + def id_(self, value: ID): + self.__id_ = value + + @property + def id(self) -> ID: + """DEPRECATED""" + return self.__id_ @id.setter def id(self, value: ID): - self._id = value + """DEPRECATED""" + self.__id_ = value def __repr__(self): return ( - f"LabelEntity({self.id}, name={self.name}, hotkey={self.hotkey}, " + f"LabelEntity({self.id_}, name={self.name}, hotkey={self.hotkey}, " f"domain={self.domain}, color={self.color})" ) def __eq__(self, other): if isinstance(other, LabelEntity): return ( - self.id == other.id + self.id_ == other.id_ and self.name == other.name and self.color == other.color and self.hotkey == other.hotkey @@ -194,12 +204,12 @@ def __eq__(self, other): def __lt__(self, other): if isinstance(other, LabelEntity): - return self.id < other.id + return self.id_ < other.id_ return False def __gt__(self, other): if isinstance(other, LabelEntity): - return self.id > other.id + return self.id_ > other.id_ return False def __hash__(self): diff --git a/ote_sdk/ote_sdk/entities/label_schema.py b/ote_sdk/ote_sdk/entities/label_schema.py index 68ee3550451..acdd5f59665 100644 --- a/ote_sdk/ote_sdk/entities/label_schema.py +++ b/ote_sdk/ote_sdk/entities/label_schema.py @@ -4,9 +4,12 @@ # SPDX-License-Identifier: Apache-2.0 # +import copy +import logging from enum import Enum -from typing import List, Optional, Sequence +from typing import Dict, List, Optional, Sequence +import numpy as np from bson import ObjectId from ote_sdk.entities.graph import Graph, MultiDiGraph @@ -14,6 +17,8 @@ from ote_sdk.entities.label import LabelEntity from ote_sdk.entities.scored_label import ScoredLabel +logger = logging.getLogger(__name__) + class LabelGroupExistsException(ValueError): """Exception thrown if the LabelGroup already exists""" @@ -53,19 +58,29 @@ def __init__( group_type: LabelGroupType = LabelGroupType.EXCLUSIVE, id: ID = None, ): - self.id = ID(ObjectId()) if id is None else id + self.id_ = ID(ObjectId()) if id is None else id - self.labels = sorted(labels, key=lambda x: x.id) + self.labels = sorted(labels, key=lambda x: x.id_) self.name = name self.group_type = group_type + @property + def id(self) -> ID: + """DEPRECATED""" + return self.id_ + + @id.setter + def id(self, value: ID): + """DEPRECATED""" + self.id_ = value + @property def minimum_label_id(self) -> ID: """ Returns the minimum (oldest) label ID, which is the first label in self.labels since this list is sorted """ - return self.labels[0].id + return self.labels[0].id_ def remove_label(self, label: LabelEntity) -> None: """ @@ -87,14 +102,14 @@ def is_single_label(self) -> bool: def __eq__(self, other: object): if not isinstance(other, LabelGroup): return False - return self.id == other.id and ( + return self.id_ == other.id_ and ( set(self.labels) == set(other.labels) and self.group_type == other.group_type ) def __repr__(self) -> str: return ( - f"LabelGroup(id={self.id}, name={self.name}, group_type={self.group_type}," + f"LabelGroup(id={self.id_}, name={self.name}, group_type={self.group_type}," f" labels={self.labels})" ) @@ -316,7 +331,7 @@ def get_labels(self, include_empty) -> List[LabelEntity]: for label in group.labels if include_empty or not label.is_empty } - return sorted(list(labels), key=lambda x: x.id) + return sorted(list(labels), key=lambda x: x.id_) def get_groups(self, include_empty: bool = False) -> List[LabelGroup]: """ @@ -371,7 +386,7 @@ def get_label_ids(self, include_empty) -> List[ID]: :param include_empty: Include empty label id or not """ label_ids = { - label.id + label.id_ for group in self._groups for label in group.labels if include_empty or not label.is_empty @@ -581,3 +596,190 @@ def from_labels(cls, labels: Sequence[LabelEntity]): """ label_group = LabelGroup(name="from_label_list", labels=labels) return LabelSchemaEntity(label_groups=[label_group]) + + def resolve_labels_probabilistic( + self, + scored_labels: List[ScoredLabel], + selected_labels: List[LabelEntity] = None, + ) -> List[ScoredLabel]: + """ + Resolves hierarchical labels and exclusivity + based on a list of ScoredLabels (labels with probability). + + The following two steps are taken: + + - selects the most likely label from an exclusive (multiclass) group + - removes children of "not-most-likely" (non-max) parents in an exclusive group (top-down approach) + + The method is intended to post-process the output of probabilistic systems such as predictions coming from + machine learning methods to resolve ambiguities and logical impossibilities. When processing (non-probabilistic) + user input please use `complete_labels` instead. + + :param label_schema: `LabelSchemaEntity` object + :param scored_labels: a list of ScoredLabels (labels with probability) + :param selected_labels: if not None, will only consider labels within `selected_labels` for resolving. + Any other labels which have relations with selected_labels (e.g. parent), + but are outside `selected_labels` are set to a default probability of 1.0 + """ + input_domains = set(lbl.domain for lbl in scored_labels) + label_to_probability = { + scored_label.get_label(): scored_label.probability + for scored_label in scored_labels + } + resolved_labels = self.__resolve_labels_probabilistic( + label_to_probability, selected_labels + ) + output_domains = set(lbl.domain for lbl in resolved_labels) + if input_domains != output_domains: + logger.error( + "Something went wrong in 'resolve_labels_probabilistic', " + "some tasks (domains) lost all their labels; " + "label_schema: %s input_labels: %s output_labels: %s", + self, + scored_labels, + resolved_labels, + ) + return resolved_labels + + def __resolve_labels_probabilistic( + self, + label_to_probability: Dict[LabelEntity, float], + selected_labels: Optional[Sequence[LabelEntity]], + ) -> List[ScoredLabel]: + """ + Resolves hierarchical labels and exclusivity + based on a probabilistic label output (map from `Label` to float) + + - selects the most likely (max) label from an exclusive group + - removes children of non-max parents in an exclusive group + + See `resolve_labels_probabilistic` for parameter descriptions + + """ + # add (potentially) missing ancestors labels for children with probability 0 + # this is needed so that suppression of children of non-max exclusive labels works when the exclusive + # group has only one member + label_to_probability = self.__add_missing_ancestors( + label_to_probability, selected_labels + ) + + hard_classification = self.__resolve_exclusive_labels(label_to_probability) + + # suppress the output of children of parent nodes that are not the most likely label within their group + resolved = self.__suppress_descendant_output(hard_classification) + + result = [] + for label, probability in resolved.items(): + if probability > 0: # only return labels with non-zero probability + result.append( + ScoredLabel( + label, + probability=( + probability + * label_to_probability.get(label, 1.0) + # retain the original probability in the output + ), + ) + ) + return result + + def __suppress_descendant_output( + self, hard_classification: Dict[LabelEntity, float] + ) -> Dict[LabelEntity, float]: + """ + Suppresses outputs in `label_to_probability` (sets probability to 0.0) for descendants of parents that have + 0 probability in `hard_classification` + """ + + # Input: Conditional probability of each label given its parent label + # Output: Marginal probability of each label + + # We recursively compute the marginal probability of each node by multiplying the conditional probability + # with the marginal probability of its parent. That is: + # P(B) = P(B|A) * P(A) + # The recursion is done a topologically sorted list of labels to ensure that the marginal probability + # of the parent label has been computed before trying to compute the child's probability. + + label_tree = self.label_tree + all_labels = label_tree.get_labels_in_topological_order() + + for child in all_labels: + if child in hard_classification: + # Get the immediate parents (should be at most one element; zero for root labels) + parents = label_tree.neighbors(child) + + if len(parents) > 0: + parent = parents[0] + if parent in hard_classification: + hard_classification[child] *= hard_classification[parent] + + return hard_classification + + def __resolve_exclusive_labels( + self, label_to_probability: Dict[LabelEntity, float] + ) -> Dict[LabelEntity, float]: + """ + For labels in `label_to_probability` sets labels that are most likely (maximum probability) in their exclusive + group to 1.0 and other (non-max) labels to probability 0. + """ + hard_classification: Dict[LabelEntity, float] = {} + top_level_labels_in_label_schema = [ + label_ + for label_ in self.label_tree.get_labels_in_topological_order() + if self.get_parent(label_) is None + ] + + for label, probability in label_to_probability.items(): + if label not in hard_classification: + label_parent = self.get_parent(label) + if label_parent is None: + # The label itself is a top-level label + exclusive_neighbours = [ + label_ + for label_ in top_level_labels_in_label_schema + if label_ != label + ] + else: + exclusive_neighbours = [ + label_ + for label_ in self.get_children(label_parent) + if label_ != label + ] + + probabilities = [probability] + neighbours_ = [label] + for neighbor in exclusive_neighbours: + neighbours_.append(neighbor) + probabilities.append(label_to_probability.get(neighbor, 0)) + if len(probabilities) > 1: + max_index = np.argmax(probabilities) + for idx, neighbor in enumerate(neighbours_): + hard_classification[neighbor] = float(max_index == idx) + else: + # single node group, interpret as multilabel node + hard_classification[label] = float( + label_to_probability[label] > 0.0 + ) + return hard_classification + + def __add_missing_ancestors( + self, + label_to_probability: Dict[LabelEntity, float], + selected_labels: Optional[Sequence[LabelEntity]], + ) -> Dict[LabelEntity, float]: + """ + Adds missing ancestors (of the same task) to the `label_to_probability` map. + Missing ancestors get probability `probability` + """ + updated_label_to_probability = copy.deepcopy(label_to_probability) + for label in label_to_probability: + for ancestor in self.get_ancestors(label): + if ancestor not in updated_label_to_probability: + updated_label_to_probability[ancestor] = ( + 0.0 # by default missing ancestors get probability 0.0 + if selected_labels is None + else (ancestor not in selected_labels) * 1.0 + # ... unless label selection is used, in that case + # the ancestor will get probability 1.0 if it is missing + ) + return updated_label_to_probability diff --git a/ote_sdk/ote_sdk/entities/model.py b/ote_sdk/ote_sdk/entities/model.py index ebd0f1a78d5..b77d4fc1a52 100644 --- a/ote_sdk/ote_sdk/entities/model.py +++ b/ote_sdk/ote_sdk/entities/model.py @@ -9,7 +9,6 @@ from ote_sdk.configuration import ConfigurableParameters from ote_sdk.entities.id import ID -from ote_sdk.entities.label import LabelEntity from ote_sdk.entities.label_schema import LabelSchemaEntity from ote_sdk.entities.metrics import NullPerformance, Performance from ote_sdk.entities.model_template import TargetDevice @@ -46,8 +45,6 @@ class ModelConfiguration: """ configurable_parameters: ConfigurableParameters - labels: List[LabelEntity] - label_schema: LabelSchemaEntity def __init__( self, @@ -55,7 +52,11 @@ def __init__( label_schema: LabelSchemaEntity, ): self.configurable_parameters = configurable_parameters - self.label_schema = label_schema + self.__label_schema = label_schema + + def get_label_schema(self) -> LabelSchemaEntity: + """Get the LabelSchema""" + return self.__label_schema class ModelFormat(IntEnum): @@ -135,7 +136,7 @@ def __init__( if model_adapters is None: model_adapters = {} - self.__id = _id + self.__id_ = _id self.__creation_date = creation_date self.__train_dataset = train_dataset self.__previous_trained_revision = previous_trained_revision @@ -161,13 +162,23 @@ def __init__( self.__model_size_reduction = model_size_reduction @property - def id(self) -> ID: + def id_(self) -> ID: """Gets or sets the id of a Model""" - return self.__id + return self.__id_ + + @id_.setter + def id_(self, value: ID): + self.__id_ = value + + @property + def id(self) -> ID: + """DEPRECATED""" + return self.__id_ @id.setter def id(self, value: ID): - self.__id = value + """DEPRECATED""" + self.__id_ = value @property def configuration(self) -> ModelConfiguration: @@ -458,7 +469,7 @@ def is_optimized(self) -> bool: def __eq__(self, other): if isinstance(other, ModelEntity): return ( - self.id == other.id + self.id_ == other.id_ and self.train_dataset == other.train_dataset and self.performance == other.performance ) diff --git a/ote_sdk/ote_sdk/entities/resultset.py b/ote_sdk/ote_sdk/entities/resultset.py index e7bdf4212fd..fd9d016aacf 100644 --- a/ote_sdk/ote_sdk/entities/resultset.py +++ b/ote_sdk/ote_sdk/entities/resultset.py @@ -80,7 +80,7 @@ def __init__( id = ID() if id is None else id performance = NullPerformance() if performance is None else performance creation_date = now() if creation_date is None else creation_date - self.__id = id + self.__id_ = id self.__model = model self.__prediction_dataset = prediction_dataset self.__ground_truth_dataset = ground_truth_dataset @@ -89,13 +89,23 @@ def __init__( self.__creation_date = creation_date @property - def id(self) -> ID: + def id_(self) -> ID: """Returns the id of the ResultSet""" - return self.__id + return self.__id_ + + @id_.setter + def id_(self, value: ID) -> None: + self.__id_ = value + + @property + def id(self) -> ID: + """DEPRECATED""" + return self.__id_ @id.setter - def id(self, value: ID) -> None: - self.__id = value + def id(self, value: ID): + """DEPRECATED""" + self.__id_ = value @property def model(self) -> ModelEntity: @@ -170,5 +180,5 @@ def __repr__(self): f"purpose={self.purpose}, " f"performance={self.performance}, " f"creation_date={self.creation_date}, " - f"id={self.id})" + f"id={self.id_})" ) diff --git a/ote_sdk/ote_sdk/entities/scored_label.py b/ote_sdk/ote_sdk/entities/scored_label.py index d2b5419551b..1b01465000b 100644 --- a/ote_sdk/ote_sdk/entities/scored_label.py +++ b/ote_sdk/ote_sdk/entities/scored_label.py @@ -31,10 +31,15 @@ def name(self) -> str: return self.label.name @property - def id(self) -> ID: + def id_(self) -> ID: """ Returns the label id. """ + return self.label.id_ + + @property + def id(self) -> ID: + """DEPRECATED""" return self.label.id @property @@ -80,14 +85,14 @@ def get_label(self) -> LabelEntity: def __repr__(self): return ( - f"ScoredLabel({self.id}, name={self.name}, probability={self.probability}, " + f"ScoredLabel({self.id_}, name={self.name}, probability={self.probability}, " f"domain={self.domain}, color={self.color}, hotkey={self.hotkey})" ) def __eq__(self, other): if isinstance(other, ScoredLabel): return ( - self.id == other.id + self.id_ == other.id_ and self.name == other.name and self.color == other.color and self.hotkey == other.hotkey diff --git a/ote_sdk/ote_sdk/serialization/label_mapper.py b/ote_sdk/ote_sdk/serialization/label_mapper.py index 8b713adc327..2a3621227c1 100644 --- a/ote_sdk/ote_sdk/serialization/label_mapper.py +++ b/ote_sdk/ote_sdk/serialization/label_mapper.py @@ -60,7 +60,7 @@ def forward( """Serializes to dict.""" return { - "_id": IDMapper().forward(instance.id), + "_id": IDMapper().forward(instance.id_), "name": instance.name, "color": ColorMapper().forward(instance.color), "hotkey": instance.hotkey, @@ -100,9 +100,9 @@ def forward(instance: LabelGroup) -> dict: """Serializes to dict.""" return { - "_id": IDMapper().forward(instance.id), + "_id": IDMapper().forward(instance.id_), "name": instance.name, - "label_ids": [IDMapper().forward(label.id) for label in instance.labels], + "label_ids": [IDMapper().forward(label.id_) for label in instance.labels], "relation_type": instance.group_type.name, } @@ -133,9 +133,9 @@ def forward(instance: Union[LabelGraph, LabelTree]) -> dict: return { "type": instance.type, "directed": instance.directed, - "nodes": [IDMapper().forward(label.id) for label in instance.nodes], + "nodes": [IDMapper().forward(label.id_) for label in instance.nodes], "edges": [ - (IDMapper().forward(edge[0].id), IDMapper().forward(edge[1].id)) + (IDMapper().forward(edge[0].id_), IDMapper().forward(edge[1].id_)) for edge in instance.edges ], } @@ -188,7 +188,7 @@ def forward( "label_tree": LabelGraphMapper().forward(instance.label_tree), "label_groups": label_groups, "all_labels": { - IDMapper().forward(label.id): LabelMapper().forward(label) + IDMapper().forward(label.id_): LabelMapper().forward(label) for label in instance.get_labels(True) }, } diff --git a/ote_sdk/ote_sdk/test_suite/ARCHITECTURE.md b/ote_sdk/ote_sdk/test_suite/ARCHITECTURE.md new file mode 100644 index 00000000000..c7cc623f49d --- /dev/null +++ b/ote_sdk/ote_sdk/test_suite/ARCHITECTURE.md @@ -0,0 +1,1369 @@ +# OTE SDK test suite architecture + +## I. General description + +The folder `ote_sdk/ote_sdk/test_suite/` contains `ote_sdk.test_suite` library that +simplifies creation of training tests for OTE algo backend. + +The training tests are tests that may run in some unified manner such stages as +* training of a model, +* evaluation of the trained model, +* export or optimization of the trained model, +* and evaluation of exported/optimized model. + +Typically each OTE algo backend contains test file `test_ote_training.py` that allows to run the +training tests. + +Note that there are a lot of dependencies between different stages of training tests: most of them +require trained model, so they depends on training stage; also for example POT optimization stage +and evaluation of exported model stage require the exported model, so export stage should be run +before, etc. + +The `test_suite` library allows to create training tests such that +1. the tests do not repeat the common steps that can be re-used +2. if we point for pytest that only some test stage is required, all dependency stages are run + automatically +3. if a stage is failed all the stage that depend on this stage are also failed. + +Note that the second item above is absent in such pytest library as `pytest-dependency` that just +skip a test if any of the dependencies did fail or has been skipped. + +To avoid repeating of the common steps between stages the results of stages should be kept in a +special cache to be re-used by the next stages. + +We suppose that each test executes one test stage (also called test action). + +## II. General architecture overview + +Here and below we will write paths to test suite library files relatively with the folder +`ote_sdk/ote_sdk` of OTE git repository, so path to this file is referred as +`test_suite/ARCHITECTURE.md`. + +When we run some test that uses `test_suite` library (typically `test_ote_training.py` in some of +the algo backends) the callstack of the test looks as follows: + +* Pytest framework + +* Instance of a test class. + Typically this class is defined in `test_ote_training.py` in the algo backend. + This class contains some fixtures implementation and uses test helper (see the next item). + The name of the class is started from `Test`, so pytest uses it as a usual test class. + The instance is responsible on the connection between test suite and pytest parameters and + fixtures. + +* Instance of training test helper class `OTETestHelper` from `test_suite/training_tests_helper.py`. + The instance of the class should be a static field of the test class stated above. + The instance controls all execution of tests. + Also the instance keeps in its cache an instance of a test case class between runs of different + tests (see the next item). + +* Instance of a test case class. + This instance connects all the test stages between each other and keeps in its fields results of + all test stages between tests. + (Since the instance of this class is kept in the cache of training test helper's instance between + runs of tests, results of one test may be re-used by other tests.) + Note that each test executes only one test stage. + And note that the class of the test case is generated "on the fly" by the function + `generate_ote_integration_test_case_class` from the file `test_suite/training_test_case.py`; + the function + * receives as the input the list of action classes that should be used in tests for the + algo backend + * and returns the class type that will be used by the instance of the test helper. + +* Instance of the test stage class `OTETestStage` from `test_suite/training_tests_stage.py`. + The class wraps a test action class (see the next item) to run it only once. + Also it makes validation of the results of the wrapped test action if this is required. + +* Instance of a test action class. + The class makes the real actions that should be done for a test using calls of OTE SDK interfaces. + +The next sections will describe the corresponding classes from the bottom to the top. + + +## III. Test actions + +### III.1 General description of test actions classes + +The test action classes in test suite make the real work. + +Each test action makes operations for one test stage. At the moment the file +`test_suite/training_tests_actions.py` contains the reference code of the following test actions +for mmdetection algo backend: +* class `OTETestTrainingAction` -- training of a model +* class `OTETestTrainingEvaluationAction` -- evaluation after the training +* class `OTETestExportAction` -- export after the training +* class `OTETestExportEvaluationAction` -- evaluation of exported model +* class `OTETestPotAction` -- POT compression of exported model +* class `OTETestPotEvaluationAction` -- evaluation of POT-compressed model +* class `OTETestNNCFAction` -- NNCF-compression of the trained model +* class `OTETestNNCFGraphAction` -- check of NNCF compression graph (work on not trained model) +* class `OTETestNNCFEvaluationAction` -- evaluation of NNCF-compressed model +* class `OTETestNNCFExportAction` -- export of NNCF-compressed model +* class `OTETestNNCFExportEvaluationAction` -- evaluation after export of NNCF-compressed model + +Note that these test actions are implementation for mmdetection algo backend due to historical +reasons. +But since the actions make operations using OTE SDK interface, most of test actions code may be +re-used for all algo backends. + +One of obvious exceptions is the training action -- it uses real datasets for a concrete algo +backend, and since different algo backends have their own classes for datasets (and may could have a +bit different ways of loading of the datasets) the training action should be re-implemented for each +algo backends. + +Note that each test action class MUST have the following properties: +* it MUST be derived from the base class `BaseOTETestAction`; +* it MUST override the static field `_name` -- the name of the action, it will be used as a unique + identifier of the test action and it should be unique for the algo backend; +* if validation of the results of the action is required, it MUST override the static field + `_with_validation` and set `_with_validation = True`; +* if it depends on the results of other test actions, it MUST override the field + `_depends_stages_names`, the field should be a list of `str` values and should contain + all the names of actions that's results are used in this action + (the desired order of the names could be the order how the actions should be executed, but note + that even in the case of another order in this list the dependent actions will be executed in the + correct order); +* (NB: the most important) it MUST override the method `__call__` -- the method should execute the + main action of the class and return a dict that will be stored as the action results. + +Please, note that the method `__call__` of an action class MUST also have the following declaration: +```python + def __call__(self, data_collector: DataCollector, results_prev_stages: OrderedDict): +``` +It receives as the first parameter the `DataCollector` class that allows to store some results of +execution of the action into the test system's database +(if the test is executed on our CI system, these results will be stored to the centralized database +of our CI that could be accessed through several dashboards). + +Also it receives as the second parameter `results_prev_stages` -- it is an `OrderedDict` that +contains all the results of the previous stages: +* each key is a name of test action +* each value is a dict, that was returned as the result of the action. + +The `__call__` method MUST return as the result a dict that will be stored as the result of the +action (an empty dict is acceptable). + +**Example:** +The class `OTETestTrainingAction` in the file `test_suite/training_tests_actions.py` +implements the training action for mmdetection, it has `_name = "training"` and its method +`__call__` returns as the result a dict +```python + results = { + "model_template": self.model_template, + "task": self.task, + "dataset": self.dataset, + "environment": self.environment, + "output_model": self.output_model, + } +``` +It means that the action class `OTETestTrainingEvaluationAction` that makes evaluation after +training in its method `__call__` can use +```python + kwargs = { + "dataset": results_prev_stages["training"]["dataset"], + "task": results_prev_stages["training"]["task"], + "trained_model": results_prev_stages["training"]["output_model"], + } +``` + +### III.2 When implementation of own test action class is required + +Please, note that `test_suite/training_tests_actions.py` contains reference code of actions for +mmdetection algo backend. This is done due to historical reasons and due to fact that mmdetection is +the first algo backend used in OTE SDK. + +As we stated above, fortunately, most of test actions may be re-used for other algo backends, since +to make some test action the same OTE SDK calls should be done. + +But if for an algo backend some specific test action should be done, an additional test action class +could be also implemented for the algo backend (typically, in the file `test_ote_training.py` in the +folder `tests/` of the algo backend). + +Also if an algo backend should make some test action in a bit different way than in mmdetection, the +test action for the algo backend should be re-implemented. + +*Example:* For MobileNet models in image classification algo backend the NNCF compression requires +loading of the secondary (auxiliary) model. (It is required since NNCF compression requires +training, and for training MobileNet models deep-object-reid algo backend uses a specific auxiliary +model as a regularizer.) + +Please, note that if you re-implementing a test action class for an algo backend it is HIGHLY +RECOMMENDED that it returns as the result dict with THE SAME keys as for the original test action +class in `test_suite/training_tests_actions.py`, and, obviously, the values for the keys have the +same meaning as for the original class. It is required since other test actions could use the result +of this test action, and if you replace a test action you should keep its interface for other +actions classes -- otherwise you will have to re-implement also all the test actions classes that +depends on this one. + +Also there is a case when a new test action class should be additionally implemented in +`test_suite/training_tests_actions.py` -- when we found out that addition test action should be used +for all algo backends. + +### III.3 How to implement own test action class + +Please, note that this section covers the topic how to implement a new test action class, but does +not cover the topic how to make the test action class to be used by tests -- it is covered below in +the section TODO[should be written]. + +To implement your own test action you should do as follows: +1. Create a class derived from `OTETestTrainingAction` +2. Set in the class the field `_name` to the name of the action +3. Set in the class the field `_with_validation = True` if validation of the action results is + required +4. Set in the class the field `_depends_stages_names` to the list of `str` values of the names of + test actions which results will be used in this test +5. Implement a protected method of the class which makes the real work by calling OTE SDK operations + NB: the method should receive the parameter `data_collector: DataCollector` and use it to + store some results of the action to the CI database + (see how the class `DataCollector` is used in several actions in + `test_suite/training_tests_actions.py`) +6. Implement the method `__call__` of the class with the declaration + `def __call__(self, data_collector: DataCollector, results_prev_stages: OrderedDict):` + See as the reference the method `__call__` of the class `OTETestTrainingEvaluationAction` + from the file `test_suite/training_tests_actions.py`. + The method should work as follows: + * call `self._check_result_prev_stages(results_prev_stages, self.depends_stages_names)` + (NB: this is a required step, it will allow to catch important errors if you connect several + test actions with each other in a wrong way) + * get from the field `results_prev_stages` results of previous stages that should be used + and convert them to the arguments of the protected method in the item 5 above + * call the protected function from the item 5 above + * the results of the method convert to a dict and return the dict from the method `__call__` + to store them as the result of the action + +## IV. Test stage class + +### IV.1 General description of test stage class + +The class `OTETestStage` from `test_suite/training_tests_stage.py` works as a wrapper for a test +action. For each instance of a test action an instance of the class `OTETestStage` is created. + +It's constructor has declaration +```python +def __init__(self, action: BaseOTETestAction, stages_storage: OTETestStagesStorageInterface): +``` + +* The `action` parameter here is the instance of action that is wrapped. + It is kept inside the `OTETestStage` instance. +* The `stages_storage` here is an instance of a class that allows to get a stage by name, this will + be a test case class that connects all the test stages between each other and keeps in its fields + results of all test stages between tests + (all the test case classes are derived from OTETestStagesStorageInterface) + +The `stages_storage` instance is also kept inside `OTETestStage`, it will be used to get for each +stage its dependencies. +Note that the abstract interface class `OTETestStagesStorageInterface` has the only abstract method +`get_stage` with declaration +```python +def get_stage(self, name: str) -> "OTETestStage": +``` +-- it returns test stage class by its name. + +Note that test stage has the property `name` that returns the name of its action +(i.e. the name of a stage equals to the name of the wrapped action). + +The class `OTETestStage` has method `get_depends_stages` that works as follows: +1. get for the wrapped action the list of names from its field `_depends_stages_names` using the + property `depends_stages_names` +2. for each of the name get the stage using the method `self.stages_storage.get_stage(name)` + -- this will be a stage (instance of `OTETestStage`) that wraps the action with the corresponding + name. +3. Return the list of `OTETestStage` instances received in the previous item. + +As stated above, the main purposes of the class `OTETestStage` are: +* wrap a test action class (see the next item) to run it only once, together with all its + dependencies +* make validation of the results of the wrapped test action if this is required. + +See the next sections about that. + +### IV.2 Running a test action through its test stage + +The class `OTETestStage` has a method `run_once` that has the following declaration +```python + def run_once( + self, + data_collector: DataCollector, + test_results_storage: OrderedDict, + validator: Optional[Validator], + ): +``` +The parameters are as follows: +* `data_collector` -- interface to connect to CI database, see description of the methods `__call__` + of the actions in the section "III.1 General description of test actions classes." +* `test_results_storage` -- it is an OrderedDict where the results of the tests are kept between + tests, see description of the parameter `results_prev_stages` in the section + "III.1 General description of test actions classes." +* `validator` -- optional parameter, if `Validator` instance is passed, then validation may be done + (see the next section "IV.3 Validation of action results"), otherwise validation is skipped. + + + +The method works as follows: +1. runs the dependency chain of this stage using recursive call of `run_once` as follows: + * Get all the dependencies using the method `OTETestStage.get_depends_stages` described in the + previous section -- it will be the list of other `OTETestStage` instances. + * For each of the received `OTETestStage` call the method `run_once` -- it is the recursion step + Attention: in the recursion step the method `run_once` is called with parameter + `validator=None` to avoid validation during recursion step -- see details in the next section + "IV.3 Validation of action results" +2. runs the action of the stage only once: + * If it was not run earlier -- run the action + * if the action executed successfully + * store result of the action into `test_result_storage` parameter + * run validation if required + * return + * if the action executed with exception + * store the exception in a special field + * re-raise the exception + * If it was already run earlier, check if there is stored exception + * if there is no stored exception -- it means that the actions was successful + and its result is already stored in the `test_result_storage` parameter + * run validation if required + (see details in the next section) + * return + * if there is a stored exception -- it means that the actions was NOT successful + * re-raise the exception + +As you can see if an exception is raised during some action, all the actions that depends on this +one will re-raise the same exception. + +Also as you can see if we run a test for only one action, the `run_once` call of the stage will run +actions in all the dependent stages and use their results, but when we run many tests each of the +test also will call `run_once` for all the stages in the dependency chains, but the `run_once` calls +will NOT re-run actions for the tests. + + +### IV.3 Validation of action results -- how it works + +As stated above, one of the purposes of `OTETestStage` is validation of results of the wrapped +action. + +As you can see from the previous section the validation is done inside `run_once` method, +and the necessary (but not sufficient) condition of running validation is that `validator` parameter +of this method is not None. + +The class `Validator` is also implemented in `test_suite/training_tests_stage.py` file. +It has only one public method `validate` that has the declaration +```python + def validate(self, current_result: Dict, test_results_storage: Dict): +``` +The parameters are: +* `current_result` -- the result of the current action +* `test_results_storage` -- an OrderedDict that stores results from the other actions that were run. + +The method returns nothing, but may raise exceptions to fail the test. + +The `Validator` compares the results of the current action with expected metrics and with results of +the previous actions. Note that results of previous actions are important, since possible validation +criteria also may be +* "the quality metric of the current action is not worse than the result of *that* action with + possible quality drop 1%" +* "the quality metric of the current action is the same as the result of *that* action with + possible quality difference 1%" + +-- these criteria are highly useful for "evaluation after export" action (quality should be almost +the same as for "evaluation after training" action) and for "evaluation after NNCF compression" +action (quality should be not worse than for "evaluation after training" action with small possible +quality drop). + +As we stated above in the previous section, when the method `run_once` runs the recursion to run +actions for the dependency chain of the current action, the method `run_once` in recursion step is +called with the parameter `validator=None`. + +It is required since +* `Validator` does not return values but just raises exception to fail the test if the required + validation conditions are not met +* so, if we ran dependency actions with non-empty `Validator`, then the action test would be failed + if some validation conditions for the dependent stages are failed -- this is not what we want to + receive, since we run the dependency actions just to receive results of these actions +* so, we do NOT do it, so we run dependency chain with `validator=None` + +Also note that there is possible (but rare) case when a stage is called from dependency chain, and +only after that it is run from a test for which this action is the main action. +For this case (as we stated above in the previous section when we described how the method +`run_once` works) we may call validation (if it is required) even if the stage was already run +earlier and was successful. +Why this case is rare? because we ask users to mention dependencies in the field +`_depends_stages_names` in the order of their execution (see description of the field), so typically +the stages are run in the right order. + +As we stated above the `validator is not None` is the necessary condition to run validation, but it +is not sufficient. +The list of sufficient conditions to run real validation in `run_once` is as follows: +* The parameter `validator` of `run_once` method satisfies `validator is not None` + (i.e. the validation is run not from the dependency chain). +* For the action the field `_with_validation == True`. + If `_with_validation == False` it means that validation for this action is impossible -- e.g. + "export" action cannot be validated since it does not return quality metrics, but the action + "evaluation after export" is validated. +* The current test has the parameter `usecase == "reallife"`. + If a test is not a "reallife" test it means that a real training is not made for the test, + so we cannot expect real quality, so validation is not done. + See description of test parameters below in the section TODO. + +To investigate in details the conditions see the declaration of constructor of the `Validator` +class: +```python + def __init__(self, cur_test_expected_metrics_callback: Optional[Callable[[], Dict]]): +``` +As you can see it receives only one parameter, and this parameter is NOT a structure that +describes the requirements for the expected metrics for the action, but the parameter is +a FACTORY that returns the structure. + +It is required since +1. constructing the structure requires complicated operations and reading of YAML files, +2. if validation should be done for the current test, and the expected metrics for the tests are + absent, the test MUST fail + (it is important to avoid situations when developers forget to add info on expected metrics and + due to it tests are not failed) +3. but if validation for the current test is not required the test should not try to get the + expected metrics + +So to avoid checking of expected metrics structures for the tests without validation, an algo +backend a factory is used -- the factory for an action's validator is called if and only if +the action should be validated. + +The factory is implemented in the test suite as a pytest fixture -- see the fixture +`cur_test_expected_metrics_callback_fx` in the file `test_suite/fixtures.py`. + +The fixture works as follows: +* receives from other fixtures contents of the YAML file that is pointed to pytest as the pytest + parameter `--expected-metrics-file` +* checks if the current test is "reallife" training or not (if the "usecase" parameter of the test + is set to the value "reallife"), +* if it is not reallife then validation is not required -- in this case + * the fixture returns None, + * the Validator class receives None as the constructor's parameter instead of a factory, + * Validator understands it as "skip validation" +* if this is reallife training test, the fixture returns a factory function + +The returned factory function extracts from all expected metrics the expected metrics for the +current test (and if the metrics are absent -- fail the current test). + + + +### IV.4 Validation of action results -- how expected metrics are set + +As stated in the previous section, a file with expected metrics for validation is passed to pytest +as an additional parameter `--expected-metrics-file`. +It should be a YAML file. +Such YAML files are stored in each algo backend in the following path +`tests/expected_metrics/metrics_test_ote_training.yml` +(the path relative w.r.t. the algo backend root) +Examples: +* `external/mmdetection/tests/expected_metrics/metrics_test_ote_training.yml` +* `external/deep-object-reid/tests/expected_metrics/metrics_test_ote_training.yml` +* `external/mmsegmentation/tests/expected_metrics/metrics_test_ote_training.yml` + +The expected metric YAML file should store a dict that maps tests to the expected metric +requirements. + +The keys of the dict are strings -- the parameters' part of the test id-s. This string uniquely +identifies the test, since it contains the required action, and also the description of a model, a +dataset used for training, and training parameters. + +See the detailed description how the method `OTETestHelper._generate_test_id` works in the +subsection "VI.5.5 `short_test_parameters_names_for_generating_id`" of the section +"VI.5 Methods of the test parameters interface class `OTETestCreationParametersInterface`" + +Although the id-s are unique, they have a drawback -- they are quite long, since they contain all +the info to identify the test. + +Examples of such keys are: +* `ACTION-training_evaluation,model-Custom_Object_Detection_Gen3_ATSS,dataset-bbcd,num_iters-CONFIG,batch-CONFIG,usecase-reallife` +* `ACTION-nncf_export_evaluation,model-Custom_Image_Classification_EfficinetNet-B0,dataset-lg_chem,num_epochs-CONFIG,batch-CONFIG,usecase-reallife` + +Example of the whole part of expected metrics configuration for one of mmdetection test cases +```yaml +'ACTION-training_evaluation,model-Custom_Object_Detection_Gen3_ATSS,dataset-bbcd,num_iters-CONFIG,batch-CONFIG,usecase-reallife': + 'metrics.accuracy.f-measure': + 'target_value': 0.81 + 'max_diff_if_less_threshold': 0.005 + 'max_diff_if_greater_threshold': 0.06 +'ACTION-export_evaluation,model-Custom_Object_Detection_Gen3_ATSS,dataset-bbcd,num_iters-CONFIG,batch-CONFIG,usecase-reallife': + 'metrics.accuracy.f-measure': + 'base': 'training_evaluation.metrics.accuracy.f-measure' + 'max_diff': 0.01 +'ACTION-pot_evaluation,model-Custom_Object_Detection_Gen3_ATSS,dataset-bbcd,num_iters-CONFIG,batch-CONFIG,usecase-reallife': + 'metrics.accuracy.f-measure': + 'base': 'export_evaluation.metrics.accuracy.f-measure' + 'max_diff': 0.01 +'ACTION-nncf_evaluation,model-Custom_Object_Detection_Gen3_ATSS,dataset-bbcd,num_iters-CONFIG,batch-CONFIG,usecase-reallife': + 'metrics.accuracy.f-measure': + 'base': 'training_evaluation.metrics.accuracy.f-measure' + 'max_diff_if_less_threshold': 0.01 +'ACTION-nncf_export_evaluation,model-Custom_Object_Detection_Gen3_ATSS,dataset-bbcd,num_iters-CONFIG,batch-CONFIG,usecase-reallife': + 'metrics.accuracy.f-measure': + 'base': 'nncf_evaluation.metrics.accuracy.f-measure' + 'max_diff': 0.01 +``` +As you can see in this example +* the target metric "metrics.accuracy.f-measure" for the action "evaluation after training" for this + test case is `0.81` with permissible variation `[-0.005, +0.06]` +* the target metric "metrics.accuracy.f-measure" for the action "evaluation after export" should be + the same as for the action "evaluation after training" with permissible variation `[-0.01, +0.01]` +* the target metric "metrics.accuracy.f-measure" for the action "evaluation after pot" should be + the same as for the action "evaluation after export" with permissible variation `[-0.01, +0.01]` +* the target metric "metrics.accuracy.f-measure" for the action "evaluation after nncf" should be + the same as for the action "evaluation after training" with permissible variation + `[-0.01, +infinity]` + +## V. Test Case class + +### V.1 General description of test case class + +As stated above, test case class instance connects the test stages between each other and keeps +in its fields results of the kept test stages between tests. + +Since the instance of this class is kept in the cache of training test helper's instance between +runs of tests, results of one test may be re-used by other tests. + +One of the most important question is when a test may re-use results of another test. +We can consider this from the following point of view. +We suppose that the test suite indeed do not make several independent tests, but make a set of +actions with several "test cases". +Since the test suite works with OTE, each "test case" is considered as a situation that could be +happened during some process of work with OTE, and the process may include different actions. + +Since OTE is focused on training a neural network and making some operations on the trained model, +we defined the test case by the parameters that define training process +(at least they defines it as much as it is possible for such stochastic process). + +Usually the parameters defining the training process are: +1. a model - typically it is a name of OTE template to be used +2. a dataset - typically it is a dataset name that should be used + (we use known pre-defined names for the datasets on our CI) +3. other training parameters: + * `batch_size` + * `num_training_epochs` + +We suppose that for each algo backend there is a known set of parameters that define training +process, and we suppose that if two tests have the same these parameters, then they are belong to +the same test case. +We call these parameters "the parameters defining the test case". + +But from pytest point of view there are just a lot of tests with some parameters. + +The general approach that is used to allow re-using results of test stages between test is the +following: +* The tests are grouped such that the tests from one group have the same parameters from the list + of "parameters that define the test case" -- it means that the tests are grouped by the + "test cases" +* After that the tests are reordered such that + * the test from one group are executed sequentially one-by-one, without tests from other group + between tests in one group + * the test from one group are executed sequentially in the order defined for the test actions + beforehand; +* An instance of the test case class is created once for each of the group of tests stated above + -- so, the instance of test case class is created for each "test case" described above. + +As stated above, the instance of test case class is kept inside cache in OTE Test Helper class, it +allows to use the results of the previous tests of the same test case in the current test. + +### V.2 Base interface of a test case class, creation of a test case class + +The class of the test case is generated "on the fly" by the function +`generate_ote_integration_test_case_class` from the file `test_suite/training_test_case.py`; +the function has the declaration +```python +def generate_ote_integration_test_case_class( + test_actions_classes: List[Type[BaseOTETestAction]], +) -> Type: +``` +The function `generate_ote_integration_test_case_class` works as follows: +* receives as the input the list of action classes that should be used in the test case + -- the test case will be a storage for the test stages wrapping the actions and will connect the + test stages with each other +* and returns the class type that will be used by the instance of the test helper. + +The variable with the type of test case received from the function is stored in the test helper +instance -- it is stored in a special class "test creation parameters", see about it below in the +section TODO. + +Note that the result of this function is a `class`, not an `instance` of a class. +Also note that the function receives list of action `classes`, not `instances` -- the instances of +test action classes are created when the instance of the test case class is created. + +The class of the test case for a test is always inherited from the abstract interface class +`OTETestCaseInterface`. +It is derived from the abstract interface class `OTETestStagesStorageInterface`, so it has the +abstract method `get_stage` that for a string `name` returns test stage instance with this name. + +The interface class `OTETestCaseInterface` has two own methods: +* abstract classmethod `get_list_of_test_stages` without parameters that returns the list of names + of test stages for this test case +* abstract method `run_stage` that runs a stage with pointed name, the method has declaration +```python + @abstractmethod + def run_stage(self, stage_name: str, data_collector: DataCollector, + cur_test_expected_metrics_callback: Optional[Callable[[], Dict]]): +``` + +When the test case method `run_stage` is called, it receives as the parameters +* `stage_name` -- the name of the test stage to be called +* `data_collector` -- the `DataCollector` instance that is used when the method `run_once` of the + test stage is called +* `cur_test_expected_metrics_callback` -- a factory function that returns the expected metrics for + the current test, the factory function is used to create the `Validator` instance that will make + validation for the current test. + +The method `run_stage` of a created test case class always does the following: +1. checks that `stage_name` is a known name of a test stage for this test case +2. creates a `Validator` instance for the given `cur_test_expected_metrics_callback` +3. finds the test stage instance for the given `stage_name` and run for it `run_once` method as + described above in the section "IV.2 Running a test action through its test stage" with the + parameters `data_collector` and validator + +If we return back to the `OTETestCaseInterface`, we can see that the test case class derived from it +should implement the classmethod `get_list_of_test_stages` without parameters that returns the list +of names of test stages for this test case. + +Note that this method `get_list_of_test_stages` is a classmethod, since it is used when pytest +collects information on tests, before the first instance of the test case class is created. + +> NB: We decided to make the test case class as a class that is generated by a function instead of a +> "normal" class, since we would like to encapsulate everything related to the test case in one +> entity -- due to it the method`get_list_of_test_stages` is not a method of a separate entity, but +> a classmethod of the test case class. +> This could be changed in the future. + +Also note that the function `generate_ote_integration_test_case_class` does not makes anything +really complicated for creation of a test case class: all test case classes are the same except the +parameter `test_actions_classes` with the list of action classes that is used to create test stage +wrapper for each of the test action from the list. + +### V.3 The constructor of a test case class + +As stated above, the function `generate_ote_integration_test_case_class` receives as a parameter +list of action `classes`, not `instances` -- the instances of test action classes are created when +the instance of the test case class is created. +That is during construction of test case class its constructor creates instances of all the actions. + +Each test case class created by the function `generate_ote_integration_test_case_class` has +the following constructor: +```python +def __init__(self, params_factories_for_test_actions: Dict[str, Callable[[], Dict]]): +``` + +The only parameter of this constructor is `params_factories_for_test_actions` that is +a dict: +* each key of the dict is a name of a test action +* each value of the dict is a factory function without parameters that returns the + structure with kwargs for the constructor of the corresponding action + +Note that most of the test actions do not receive parameters at all -- they receive the result of +previous actions, makes its own action, may make validation, etc. + +For this case if the dict `params_factories_for_test_actions` does not contain as a key the name of +an action, then the constructor of the corresponding action will be called without parameters. + +The constructor works as follows: +* For each action that was passed to the function `generate_ote_integration_test_case_class` during + creation of this test case class + * take name of the action + * take `cur_params_factory = params_factories_for_test_actions.get(name)` + * if the result is None, `cur_params = {}` + * otherwise, `cur_params = cur_params_factory()` + * call constructor of the current action as + `cur_action = action_cls(**cur_params)` + * wraps the current action with the class `OTETestStage` as follows: + `cur_stage = OTETestStage(action=cur_action, stages_storage=self)` + * store the current stage instance as + `self._stages[cur_name] = cur_stage` + +As you can see for each factory in the dict `params_factories_for_test_actions` the factory is +called lazily -- it means, it is called when and only when the corresponding action should be +created. + +Also as you can see the dict `params_factories_for_test_actions` with the factories is passed to the +constructor as the parameter -- so, the factories may be different for each test to pass to the test +case the values corresponding to the current test. + +## VI. Test Helper class + +### VI.1 General description + +Training test helper class `OTETestHelper` is implemented in `test_suite/training_tests_helper.py`. +An instance of the class controls all execution of tests and keeps in its cache an instance of a +test case class between runs of different tests. + +The most important method of the class are +* `get_list_of_tests` -- allows pytest trick generating test parameters for the test class. + When pytest collects the info on all tests, the method returns structures that allows to make + "pytest magic" to group and reorder the tests (see details below). +* `get_test_case` -- gets an instance of the test case class for the current test parameters, allows + re-using the instance between several tests. + +Note that the both of the methods work with test parameters that are used by pytest. + +### VI.2 How pytest works with test parameters + +#### VI.2.1 Short description how pytest works + +Since `OTETestHelper` makes all the operations related to pytest parametrization mechanisms, we need +to describe here how pytest works with test parameters. + +Generally pytest works as follows: +(NB: it is a short and may be approximate description! do not use it as a pytest documentation) +1. Pytest collects test info, for each test function or test method it gets information on + parameters of the test and possible combination of parameters that may be executed. +2. Then pytest makes filtering -- it selects/deselects tests based on the pytest parameters + (e.g. `-k`) and the names of the tests + -- each test with some combination of parameters has a full name of "test with parameters" that + uniquely identifies the test with the parameters +2. Then pytest executes the selected tests one by one. + When pytest executes a test function or a test method it gets a concrete combinations of + parameter values for the parameters of the test and executes the test function/method with this + combination. + During the execution pytest may print the full name of the "test with parameters" + +#### VI.2.2 How pytest gets information on parameters + +In pytest the information on test parameters for each test function/method consists of the following +3 elements: +(NB: it is a short and may be approximate description! do not use it as a pytest documentation) +1. `argnames` -- a tuple of names of parameters of the test, typically this is a short tuple of + strings + * its length is the number of parameters of the test, + * it contains string names of the parameters +2. `argvalues` -- a list of parameters of the test, this is a long list, + * its length is the number of different combination of parameter values for the test, + * each element of the list should be a tuple, + * the length of each of the tuples is the same as the length of `argnames` above, + * the tuple stores a concrete combination of values of the parameters +3. `ids` -- a list of string identifiers, + * the list has the same length as the list `argvalues` + * each value is a string + * the string is used as an ID of the concrete combination of parameters + particularly, this parameters ID is used when pytest generates the full name of the + "test with parameters" + (as stated above it is required for printing the full name or when some filtering is made in + pytest on full test names) + -- note that usually this full name in pytest looks as + `test_name + "[" + parameters_ID + "]"` + +Usually pytest collects this information inside itself, but our test suite uses special interface +that allows to change it: if pytest finds the function `pytest_generate_tests` with declaration +```python +def pytest_generate_tests(metafunc): +``` +then special "pytest magic" is allowed. This 'pytest magic" allows sets for a concrete test +function/method the three elements stated above. + +See a bit more details how this pytest magic works in the description of the function +`ote_pytest_generate_tests_insertion` below in the section TODO. + +#### VI.2.3 How pytest runs a test with a combination of parameters + +When pytest runs a test function/method that has some parameters, pytest works as follows: +(NB: it is a short and may be approximate description! do not use it as a pytest documentation) +1. gets the triplet `argnames, argvalues, ids` for this test function/method +2. check that the test function/method has all the parameters with names from the tuple `argnames` +2. makes filtering (selecting/deselecting) of concrete parameter values combinations as on pairs of + `zip(argvalues, ids)` based on `ids` string identifiers and different pytest command line + arguments (see pytest option `-k`) +3. for each selected combination of parameter values -- a pair `(arvalue_el, id)` from + `zip(argvalues, ids)` -- do the following: + * check that `argvalue_el` is a tuple with the length equal to `argnames` + * create kwargs dict for the test function/method + * sets in the kwargs dict for each key from `argnames` the corresponding value from + `argvalue_el` probably in the following manner: + `for i in range(len(argnames)): kwargs[argnames[i]] = argvalue_el[i]` + +### VI.3 How pytest parametrization mechanisms relates to the test suite and `OTETestHelper` + +**(IMPORTANT)** The description how pytest works with test functions/methods parametrization in the +previous section relates to all pytest-based code. +But we would like to describe some important points related to `OTETestHelper` and the test suite as +a whole: + +* typically for one OTE task type for all training tests there is only one test class with only only + one test method that has a lot of combination of test parameters values +* the method `get_list_of_tests` of `OTETestHelper` returns this triplet + `argnames, argvalues, ids` that is used later in `pytest_generate_tests`-related pytest magic to + parametrize this test method + Note that the triplet `argnames, argvalues, ids` received from `get_list_of_tests` is used as is + without any changes. +* `OTETestHelper` always defines `argnames = ("test_parameters",)`, so formally the only test method + uses **only one** test parameter to parametrise tests, but values of the parameter are dict-s that + contain info on real test parameters + +### VI.4 Constructor of the class `OTETestHelper` + +The constructor of the class `OTETestHelper` has the following declaration +```python +def __init__(self, test_creation_parameters: OTETestCreationParametersInterface): +``` + +As you can see it receives as the only parameter the class that is derived from +`OTETestCreationParametersInterface`. +We will refer to it as a *test parameters class* and we will refer to the base class +`OTETestCreationParametersInterface` as to *test parameters interface*. + +We suppose that such test parameter class derived from `OTETestCreationParametersInterface` contains +most of information required to connect the test suite with a concrete algo backend. +All the methods of the interface class are abstract methods without parameters that return +structures making this connection. + +Example of such implementation is the class `DefaultOTETestCreationParametersInterface` that +contains implementation of almost all the test parameter class methods for mmdetection algo backend +(mmdetection is chosen due to historical reasons). +Nevertheless, although these methods are implemented for mmdetection, most of them may +be used without modification (or with only slight modification) for other algo backends. + +The constructor of the class `OTETestHelper` indeed makes the following: +* calls the methods of the received parameter class instance and stores the info received as + the result of the calls in the `OTETestHelper` instance fields +* check that the info stored in `OTETestHelper` instance fields has a proper structure +* initialize a cache to store a test case class + + +### VI.5 Methods of the test parameters interface class `OTETestCreationParametersInterface` + +Let's consider all the methods of the abstract test parameters interface class one by one: +* `test_case_class` +* `test_bunches` +* `default_test_parameters` +* `test_parameters_defining_test_case_behavior` +* `short_test_parameters_names_for_generating_id` + +#### VI.5.1 `test_case_class` + +```python +@abstractmethod +def test_case_class(self) -> Type[OTETestCaseInterface]: +``` +The method returns a class that will be used as a Test Case class for training tests. +Note that it should return a class itself (not an instance of the class). + +Typically OTE Test Case class should be generated by the function +`generate_ote_integration_test_case_class` and the only parameter of the function is the list of all +test action classes that should be used in the training tests for the algo backend. + +See details above in the section "V. Test Case class" + +#### VI.5.2 `test_bunches` + +This is the most important method since it defines the scope of the tests. + +```python +@abstractmethod +def test_bunches(self) -> List[Dict[str, Any]]: +``` +The method returns a test bunches list, it defines the combinations of test parameters for +which the test suite training test should be run. + +The method should return a list of dicts, each of the dicts defines one test case -- see description +how test cases are defined in the section "V.1 General description of test case class". +We will call such a dict *"a test bunch dict"* or just a *"test bunch"*. + +All keys of the test bunch dicts are strings. + +**(IMPORTANT)** +As stated above in "VI.3 How pytest parametrization mechanisms relates to the test suite and +`OTETestHelper`" typically an algo backend for training tests has only one test class with only one +test method. +Note that in a typical situation a test bunch dict is passed to the only test method of the training +test class as the value `test_parameters` -- see again the section +"VI.3 How pytest parametrization mechanisms relates to the test suite and `OTETestHelper`" + + +Mandatory keys of the test bunch dicts are: +* `"model_name"` -- the value is a string that is the name of a model to work with as it is defined + in the template.yaml file of the model +* `"dataset_name"` -- the value is a string that is the name of the dataset, note that we use known + pre-defined names for the datasets on our CI +* `"usecase"` -- the value is a string, if it is equal to `REALLIFE_USECASE_CONSTANT="reallife"` + then validation will be run for the tests + +Also typical non-mandatory keys of the test bunch dicts are +* `"num_training_iters"` or `"num_training_epochs"` or `"patience"` -- integer parameter + restricting the training time +* `"batch_size"` -- integer parameter, affects training speed and quality + + +Note that the following additional tricks are used: +1. For the mandatory fields `"model_name"` and `"dataset_name"` the value may be not only a string, + but a list of strings -- in this case a Cartesian product of all possible pairs + `(model, dataset)` is used. + This is the reason why this method is called `test_bunches` -- since each element of the returned + list may define a "bunch" of tests +2. If a non-mandatory key in a test bunch dict is absent or equals to a string + `DEFAULT_FIELD_VALUE_FOR_USING_IN_TEST`, then it may be replaced by the corresponding default + value pointed by the method `default_test_parameters` + (see about it below in the section "VI.5.3 `default_test_parameters`") + +Note that also most of actions that make real training (e.g. `OTETestTrainingAction`) use one more +additional trick: if values either for `batch_size` key or for `num_training_iters` key in a test +bunch dict contain a string constant `KEEP_CONFIG_FIELD_VALUE="CONFIG"` instead of an integer value, +the action reads the values of such parameters from the template file of the model or internal +config of the model and do not change them. +It is important when we want to keep some training parameters "as is" for reallife tests and do not +want to point our own values for them. + +Example of a test bunch that could be in `external/mmdetection/tests/test_ote_training.py` +``` +[ + dict( + model_name=[ + 'Custom_Object_Detection_Gen3_ATSS', + 'Custom_Object_Detection_Gen3_SSD', + ], + dataset_name='dataset1_tiled_shortened_500_A', + usecase='precommit', + ), + ... + dict( + model_name=[ + 'Custom_Object_Detection_Gen3_ATSS', + 'Custom_Object_Detection_Gen3_SSD', + ], + dataset_name=[ + 'bbcd', + 'weed-coco', + 'pcd', + 'aerial', + 'dice', + 'fish', + 'vitens', + 'diopsis', + ], + num_training_iters=KEEP_CONFIG_FIELD_VALUE, + batch_size=KEEP_CONFIG_FIELD_VALUE, + usecase=REALLIFE_USECASE_CONSTANT, + ) +] +``` +-- in this example +* the first test bunch will make test suite to run tests for two models (ATDD and SSD) on the + dataset `dataset1_tiled_shortened_500_A` with non-reallife training with the default `batch_size` + and `num_training_iters` +* the second test bunch will will make test suite to run tests for two models (ATDD and SSD) on 8 of + datasets (all pairs `model,dataset` will be run) with reallife training with the `batch_size` and + `num_training_iters` from the original template config. + + +#### VI.5.3 `default_test_parameters` + +```python +@abstractmethod +def default_test_parameters(self) -> Dict[str, Any]: +``` +The method returns a dict that points for test parameters the default values. +The dict should have the following structure: +* each key is a string, it is a possible key in a test bunch dict +* each value is the default value for this test bunch dict key (typically, for `"batch_size"` +and `"num_training_iters"` it is integer). + +During construction of a test helper class its call the method `default_test_parameters` and stores +it to an inner field -- *default value dict*. + +When a test helper instance prepares the triplet `argnames, argvalues, id` for the training test +parametrization, it does it using as the base the value received from the method `test_bunches` +-- see above in the section "VI.5.2 `test_bunches`". +As stated above in those section, during this preparation sometimes it fills some fields in the test +bunch dict by the default values. + +In details, test helper in this case works as follows: +* get the default values dict received from the call of the method `default_test_parameters` of the + test parameter class +* for each key in the dict + * if the key is absent in the test bunch dict, or the test bunch dict contains for the key value + `"DEFAULT_FIELD_VALUE_FOR_USING_IN_TEST"`, then + * set in the test bunch dict for the key the value from the default value dict + +After that test helper continue work with test bunch dict as if the values always were here. + +#### VI.5.4 `test_parameters_defining_test_case_behavior` + +```python +@abstractmethod +def test_parameters_defining_test_case_behavior(self) -> List[str]: +``` +The method returns a list of strings -- names of the test parameters +(i.e. keys of test bunches dicts) that define test case behavior. + +See the detailed explanation on test cases and parameters defining test case in the section +"V.1 General description of test case class". + +When several test cases are handled, if the next test has these parameters +the same as for the previous test, the test case class is re-used for the next test. +This is what allows re-using the result of previous test stages in the next test stages. + +#### VI.5.5 `short_test_parameters_names_for_generating_id` + +```python +@abstractmethod +def short_test_parameters_names_for_generating_id(self) -> OrderedDict: +``` +This method returns an `OrderedDict` that is used to generate the `ids` part of the triplet +`argnames, argvalues, ids` that is returned by the OTE test helper method `get_list_of_tests` for +the training test parametrization. + +The returned OrderedDict has the following structure +* each key is a string that is a key of test bunch dicts that should be used for generating id-s +* each value is a short name of this key that will be used as an alias for string id-s generating + +In details, for each combination of test parameters the string identifier `id` for the parameters' +combination is generated by the method `OTETestHelper._generate_test_id` that is equivalent to the +following one: +```python + def _generate_test_id(self, test_parameters): + id_parts = [] + for par_name, short_par_name in self.short_test_parameters_names_for_generating_id.items(): + id_parts.append(f"{short_par_name}-{test_parameters[par_name]}") + return ",".join(id_parts) +``` +(here `self.short_test_parameters_names_for_generating_id` is the OrderedDict stored in the +constructor) + +Note that +* If a key of test bunch dicts is not present in this OrderedDict, then it will not be present in + the string identifier. + So it is important to have as keys all elements of the list returned by + `test_parameters_defining_test_case_behavior` in this OrderedDict. +* Since the length of test identifiers may be an issue, it is important to have as the values of the + OrderedDict descriptive, but short aliases. + +Example of such OrderedDict for mmdetection is as follows: +```python +OrderedDict( + [ + ("test_stage", "ACTION"), + ("model_name", "model"), + ("dataset_name", "dataset"), + ("num_training_iters", "num_iters"), + ("batch_size", "batch"), + ("usecase", "usecase"), + ] +) +``` + +### VI.6 How the method `OTETestHelper.get_list_of_tests` works + +As stated above, the method `get_list_of_tests` returns the triplet +`argnames, argvalues, ids` that is used later in `pytest_generate_tests`-related pytest magic to +parametrize this test method, and the triplet `argnames, argvalues, ids` received from +`get_list_of_tests` is used as is without any changes. + +The method `get_list_of_tests` of the class `OTETestHelper` works as follows: +* set `argnames = ("test_parameters",)` -- as we stated above test suite training tests always use + one parameter for pytest test, but the values of the parameter will be a dict +* get `test_bunches` list stored earlier to a field from test parameters class in constructor + See the detailed description in the section "VI.5.2 `test_bunches`" +* get the class `test_case_class` stored earlier to a field from test parameters class in + constructor + See the detailed description in the section "VI.5.1 `test_case_class`" +* initialize + `argvalues = []` + `ids = []` +* for each test bunch in the list: + * take the mandatory fields `model_name` and `dataset_name` from the test bunch dict + * create the list of pairs `(model_name, dataset_name)` to be handled: + * if either the field `model_name` or `dataset_name` is a list, generate cartesian product of + all possible pairs using `itertools.product` + * otherwise just take one pair `(model_name, dataset_name)` + * for each pair `(model_name, dataset_name)` + * for each test action name received from `test_case_class.get_list_of_test_stages()` + * make deepcopy of the test bunch dict + * set the key `"test_stage"` in the copied dict to the current test action name + * set the keys `model_name` and `dataset_name` in the copied dict to the current model name + and dataset name + * make filling of the default values in the copied test bunch dict + -- see the detailed description how it is done above in the subsection + "VI.5.3 `default_test_parameters`" of the section + "VI.5 Methods of the test parameters interface class `OTETestCreationParametersInterface`" + * generate the string id that corresponds to this combination of parameters using the method + `OTETestHelper._generate_test_id` + -- see the detailed description how this method works in the subsection + "VI.5.5 `short_test_parameters_names_for_generating_id`" of the section + "VI.5 Methods of the test parameters interface class `OTETestCreationParametersInterface`" + * append to `argvalues` the current copied-and-modified dict + * append to `ids` the generated string id +* when exit from all the cycles, return the triplet `argnames, argvalues, ids` + +What is the result of this function? + +As we stated above in the section "V.1 General description of test case class" to work properly the +test suite tests should be organized as follows: + +> * The tests are grouped such that the tests from one group have the same parameters from the list +> of "parameters that define the test case" -- it means that the tests are grouped by the +> "test cases" +> * After that the tests are reordered such that +> * the test from one group are executed sequentially one-by-one, without tests from other group +> between tests in one group +> * the test from one group are executed sequentially in the order defined for the test actions +> beforehand; + +Since for an algo backend we typically have only one test class for the training tests, only one +test method in the class, and the method is parametrized by the triplet `argnames, argvalues, ids` +received from the function `get_list_of_tests`, described above, we can say that these conditions +are fulfilled. + +### VI.7 How the method `OTETestHelper.get_test_case` works + +As stated above `get_test_case` -- gets an instance of the test case class for the current test +parameters, allows re-using the instance between several tests. + +It has the following declaration: +```python +def get_test_case(self, test_parameters, params_factories_for_test_actions): +``` +It has the following parameters: +* `test_parameters` -- the parameters of the current test, indeed it is one of elements of the list + `argvalues` from the triplet `argnames, argvalues, ids` received from the method + `get_list_of_tests` -- see the previous section how it is generated +* `params_factories_for_test_actions` -- this is a dict mapping action names to factories, + generating parameters to construct the actions, it is the same as the input parameter for the test + case class, see detailed description in the section + "V.3 The constructor of a test case class" + Note that this parameter is passed to the constructor of a test case class without any changes. + +Also as stated above in the section "V.1 General description of test case class" to make test suite +tests work properly the following should be fulfilled: + +> * An instance of the test case class is created once for each of the group of tests stated above +> -- so, the instance of test case class is created for each "test case" described above. + +Also as we stated at the bottom of the previous section, the parameters of the only test method of +the training tests are reordered in such a way that the tests from one test case are executed +sequentially, without tests from another test case between them. + +And, as also was stated in the section "V.1 General description of test case class" + +> We suppose that for each algo backend there is a known set of parameters that define training +> process, and we suppose that if two tests have the same these parameters, then they are belong to +> the same test case. +> We call these parameters "the parameters defining the test case". + +These parameters defining test case are received by test helper instance from the method +`test_parameters_defining_test_case_behavior` of the test parameters class. + +So to keep one test case class instance the method `get_test_case` of the test helper class +`OTETestHelper` works as follows: +* get the class `test_case_class` stored earlier to a field from test parameters class in + constructor + See the detailed description in the section "VI.5.1 `test_case_class`" +* get the list of string `important_params = self.test_parameters_defining_test_case_behavior` + -- get the list of names of parameters defining test case, it was stored earlier to a field from + the test parameters class + See the detailed description in the section "VI.5.4 `test_parameters_defining_test_case_behavior`" +* if we already created and stored in the cache some instance of the test case class, + * check the parameters that were used during its creation: + if for all parameters from the list `important_params` the values of + the parameters were the same + * if it is True -- it is the same test case, so the function just returns the stored instance of + the test case class +* Otherwise -- that is, if either the cache does not contain created instance of test case class, or + some parameters from the list `important_params` were changed -- tests for another test case are + started. + In this case the function creates a new instance of the class `test_case_class` passing to its + constructor the parameter `params_factories_for_test_actions` + + +## VII. Connecting algo backend with test suite. Test class in algo backend + +The direct connection between the training test in an algo backend and the test suite is made by +* Algo backend implementation of some fixtures required for test suite + -- see about that in the next section TODO +* Insertions that is made in the special algo backend file `tests/conftest.py` that is loaded by + pytest before starting its work -- all the pytest magic is inserted into it. +* Test parameter class that will provide parameters to connect the algo backend with the test suite +* A test case class in the file `tests/test_ote_training.py` in the algo backend + +Note again that before the test class there should be implemented a test parameters class that will +provide parameters to connect the algo backend with with test suite. +It should be a class derived from the test parameters interface class +`OTETestCreationParametersInterface`. +See details above in the sections "VI.4 Constructor of the class `OTETestHelper`" and +"VI.5 Methods of the test parameters interface class `OTETestCreationParametersInterface`" +As an example of the test parameters class see +* the class `ObjectDetectionTrainingTestParameters` in the file + `external/mmdetection/tests/test_ote_training.py` +* the class `ClassificationTrainingTestParameters` in the file + `external/deep-object-reid/tests/test_ote_training.py` + -- the latter is more interesting, since deep-object-reid algo backend is different w.r.t. the + mmdetection algo backend, and we implemented the default test case parameter class + `DefaultOTETestCreationParametersInterface` mostly for mmdetection. + +Note that test class class itself contains mostly a boilerplate code that connects test suite with +pytest. +(We made out the best to decrease the number of the boilerplate code, but nevertheless it is +required.) + +Also note that the test class uses a lot of fixtures implemented in test suite. + +The test case class should be implemented as follows: +* The test class should be derived from the interface class `OTETrainingTestInterface`. + This is required to distinguish the test classes implemented for the test suite: when pytest magic + related to the function `pytest_generate_tests` works, it checks if the current test class is a + subclass of this interface `OTETrainingTestInterface` and makes parametrization only in this case. + (See details on this pytest magic above in the section + "VI.2.2 How pytest gets information on parameters" and below in the section TODO) + + The interface class has only one abstract classmethod `get_list_of_tests` -- see on its + implementation below. +* The test class should have a static field `helper` defined as follows: + ```python + helper = OTETestHelper(()) + ``` +* The test class should have the following implementation of the method `get_list_of_tests` + ```python + @classmethod + def get_list_of_tests(cls, usecase: Optional[str] = None): + return cls.helper.get_list_of_tests(usecase) + ``` +* The test class should implement as its method the fixture `params_factories_for_test_actions_fx` + that will give the parameters for actions for the current test. + It should work as follows: + * use other fixtures to extract info on the current test parameters and some parameters of the + environment (e.g. the root path where datasets is placed, etc) + * create factories generating parameters for the test actions as function closures using + the info extracted from the fixtures + * and the result of the fixture is the dict `params_factories_for_test_actions` + that maps the name of each action that requires parameters to one of the factories + + **Example**: if the algo backend has two actions that require parameters in the constructors, and + the first of the action has the name "training" and its constructor has parameters + `def __init__(self, dataset, labels_schema, template_path, num_training_iters, batch_size):` + then the fixture `params_factories_for_test_actions_fx` should return a dict + `params_factories_for_test_actions` such that + `params_factories_for_test_actions["training"]` is a function closure that returns a dict + ```python + return { + 'dataset': dataset, + 'labels_schema': labels_schema, + 'template_path': template_path, + 'num_training_iters': num_training_iters, + 'batch_size': batch_size, + } + ``` +* The test class should implement as its method the fixture `test_case_fx` that will return the test + case from the current implementation using the test helper cache: if it is required the + instance of the test case class is created, otherwise the cached version of the instance is used + (See detailed description above in the section + "VI.7 How the method `OTETestHelper.get_test_case` works") + This fixture should have the following implementation + ```python + @pytest.fixture + def test_case_fx(self, current_test_parameters_fx, params_factories_for_test_actions_fx): + test_case = type(self).helper.get_test_case(current_test_parameters_fx, + params_factories_for_test_actions_fx) + return test_case + ``` +* The test class should implement as its method the fixture `data_collector_fx` that will return the + test the `DataCollector` instance + NB: probably this fixture should be moved to the common fixtures + See examples in `external/mmdetection/tests/test_ote_training.py` + +* The test class should implement as its method the only test method with the name `test` and the + following implementation: + ```python + @e2e_pytest_performance + def test(self, + test_parameters, + test_case_fx, data_collector_fx, + cur_test_expected_metrics_callback_fx): + test_case_fx.run_stage(test_parameters['test_stage'], data_collector_fx, + cur_test_expected_metrics_callback_fx) + ``` + +## VIII. Connecting algo backend with test suite. Pytest magic and fixtures. + +## VIII.1. Connecting algo backend with test suite. Pytest magic. + +As stated above in the previous section the direct connection between the training test in an algo +backend and the test suite is made, particularly, by +> * Algo backend implementation of some fixtures required for test suite +> -- see about that in the next section TODO +> * Insertions that is made in the special algo backend file `tests/conftest.py` that is loaded by +> pytest before starting its work -- all the pytest magic is inserted into it. + +The algo backend file `tests/conftest.py` is very important, since it is loaded by pytest before +many other operations, particularly, before collecting the tests. + +The file `tests/conftest.py` for algo backend should implement the following two functions +* `pytest_generate_tests` -- as we stated above in the section + "VI.2.2 How pytest gets information on parameters" it allows to override parametrization of a test + function/method + This function is called for each pytest function/method and gives the possibility to parametrize the test + through its parameter `metafunc` +* `pytest_addoption` -- the function allows to add more command line arguments to pytest, + the values passed to the command line arguments may be read later using the pytest fixture + `request`. + The function is called once before parsing of pytest command line parameters. + +In test suite the file `ote_sdk/ote_sdk/test_suite/pytest_insertions.py` contains implementations of +the special functions `ote_pytest_generate_tests_insertion` and `ote_pytest_addoption_insertion` +that makes all what is required for the test suite. + +As the result the minimal implementation of the functions `pytest_generate_tests` and +`pytest_addoption` contain the following boilerplate code only +```python +# pytest magic +def pytest_generate_tests(metafunc): + ote_pytest_generate_tests_insertion(metafunc) + +def pytest_addoption(parser): + ote_pytest_addoption_insertion(parser) +``` + +(Why we say that it is "a minimal implementation"? because the algo backend could make its own +operations in these two functions pytest, the test suite implementation of the insertions allow to +use them together with other code.) + +As we can see from the implementation `ote_pytest_generate_tests_insertion`, its main operations are +as follows: +(note that this function is called for each test function/method) +* the function get the current test class using `metafunc.cls` +* if the class is None (for test functions) or is not a subclass of `OTETrainingTestInterface`, then + return +* otherwise make + ```python + argnames, argvalues, ids = metafunc.cls.get_list_of_tests(usecase) + ``` +* parametrize the current test method by the call + ```python + metafunc.parametrize(argnames, argvalues, ids=ids, scope="class") + ``` + Note that the scope "class" is used, it is required. + +## VIII.2. Connecting algo backend with test suite. Pytest fixtures and others. + +To connect an algo backend with the test suite the following fixtures should be implemented +in the file `tests/conftest.py` of the algo backend. + +* the fixture `ote_test_domain_fx` -- it should return the string name of the + current algo backend domain +* the fixture `ote_test_scenario_fx` -- it should return the string on the + current test scenario, usually we use the following implementation + ```python + @pytest.fixture + def ote_test_scenario_fx(current_test_parameters_fx): + assert isinstance(current_test_parameters_fx, dict) + if current_test_parameters_fx.get('usecase') == REALLIFE_USECASE_CONSTANT: + return 'performance' + else: + return 'integration' + ``` +* the fixture `ote_templates_root_dir_fx` -- it should return the absolute + path of the folder where OTE SDK model templates are stored for this algo backend, usually it uses + something like `osp.dirname(osp.dirname(osp.realpath(__file__)))` to get the absolute path to the + root of the algo backend and then using knowledge of algo backend structures point to the template + path +* the fixture `ote_reference_root_dir_fx` -- it should return the absolute + path of the folder where the reference values for some test operations are stored (at the moment + such folder store the reference files for NNCF compressed graphs for the model templates). + +Also the following operations should be done +```python +pytest_plugins = get_pytest_plugins_from_ote() +ote_conftest_insertion(default_repository_name='ote/training_extensions/external/mmdetection') +``` + +The first line points to pytest additional modules from which the fixtures should be loaded -- these +may be e2e package modules and test suite fixture module. + +The second line makes some operations on variables in e2e test library that is used in our CI. diff --git a/ote_sdk/ote_sdk/tests/entities/test_annotation.py b/ote_sdk/ote_sdk/tests/entities/test_annotation.py index 38c0eae60c2..4d2177a23f8 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_annotation.py +++ b/ote_sdk/ote_sdk/tests/entities/test_annotation.py @@ -81,8 +81,8 @@ def test_annotation_default_property(self): annotation = self.annotation - assert type(annotation.id) == ID - assert annotation.id is not None + assert type(annotation.id_) == ID + assert annotation.id_ is not None assert str(annotation.shape) == "Rectangle(x=0.5, y=0.0, width=0.5, height=0.5)" assert annotation.get_labels() == [] @@ -109,9 +109,9 @@ def test_annotation_setters(self): annotation = self.annotation ellipse = Ellipse(x1=0.5, y1=0.1, x2=0.8, y2=0.3) annotation.shape = ellipse - annotation.id = ID(123456789) + annotation.id_ = ID(123456789) - assert annotation.id == ID(123456789) + assert annotation.id_ == ID(123456789) assert annotation.shape == ellipse @pytest.mark.priority_medium @@ -353,7 +353,7 @@ def test_annotation_scene_entity_default_value(self): annotation_scene_entity = self.annotation_scene_entity - assert annotation_scene_entity.id == ID() + assert annotation_scene_entity.id_ == ID() assert annotation_scene_entity.kind == AnnotationSceneKind.ANNOTATION assert annotation_scene_entity.editor_name == "" assert type(annotation_scene_entity.creation_date) == datetime.datetime @@ -384,13 +384,13 @@ def test_annotation_scene_entity_setters(self): annotation_scene_entity = self.annotation_scene_entity creation_date = self.creation_date - annotation_scene_entity.id = ID(123456789) + annotation_scene_entity.id_ = ID(123456789) annotation_scene_entity.kind = AnnotationSceneKind.PREDICTION annotation_scene_entity.editor_name = "editor" annotation_scene_entity.creation_date = creation_date annotation_scene_entity.annotations = self.annotation - assert annotation_scene_entity.id == ID(123456789) + assert annotation_scene_entity.id_ == ID(123456789) assert annotation_scene_entity.kind == AnnotationSceneKind.PREDICTION assert annotation_scene_entity.editor_name == "editor" assert annotation_scene_entity.creation_date == creation_date @@ -423,7 +423,7 @@ def test_annotation_scene_entity_magic_methods(self): f"kind={annotation_scene_entity.kind}, " f"editor={annotation_scene_entity.editor_name}, " f"creation_date={annotation_scene_entity.creation_date}, " - f"id={annotation_scene_entity.id})" + f"id={annotation_scene_entity.id_})" ] for i in annotation_scene_entity_repr: @@ -604,7 +604,7 @@ def test_null_annotation_scene_entity(self): null_annotation = NullAnnotationSceneEntity() - assert null_annotation.id == ID() + assert null_annotation.id_ == ID() assert null_annotation.kind == AnnotationSceneKind.NONE assert null_annotation.editor_name == "" assert type(null_annotation.creation_date) == datetime.datetime diff --git a/ote_sdk/ote_sdk/tests/entities/test_dataset_item.py b/ote_sdk/ote_sdk/tests/entities/test_dataset_item.py index 7bece021844..826141ad659 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_dataset_item.py +++ b/ote_sdk/ote_sdk/tests/entities/test_dataset_item.py @@ -145,6 +145,7 @@ def dataset_item(self) -> DatasetItemEntity: roi=self.roi(), metadata=self.metadata(), subset=Subset.TESTING, + ignored_labels={self.labels()[1]}, ) @@ -160,7 +161,7 @@ def compare_denormalized_annotations( expected_annotation = expected_annotations[index] # Redefining id and modification_date required because of new Annotation objects created after shape # denormalize - actual_annotation.id = expected_annotation.id + actual_annotation.id_ = expected_annotation.id_ actual_annotation.shape.modification_date = ( expected_annotation.shape.modification_date ) @@ -255,18 +256,21 @@ def test_dataset_item_initialization(self): assert default_values_dataset_item.annotation_scene == annotations_scene assert not default_values_dataset_item.metadata assert default_values_dataset_item.subset == Subset.NONE + assert default_values_dataset_item.ignored_labels == set() # Checking attributes of DatasetItemEntity object initialized with specified optional parameters roi = DatasetItemParameters().roi() metadata = DatasetItemParameters.metadata() subset = Subset.TESTING + ignored_labels = set(DatasetItemParameters().labels()) specified_values_dataset_item = DatasetItemEntity( - media, annotations_scene, roi, metadata, subset + media, annotations_scene, roi, metadata, subset, ignored_labels ) assert specified_values_dataset_item.media == media assert specified_values_dataset_item.annotation_scene == annotations_scene assert specified_values_dataset_item.roi == roi assert specified_values_dataset_item.metadata == metadata assert specified_values_dataset_item.subset == subset + assert specified_values_dataset_item.ignored_labels == ignored_labels @pytest.mark.priority_medium @pytest.mark.unit @@ -611,8 +615,8 @@ def test_dataset_item_append_annotations(self): ) dataset_item.append_annotations(annotations_to_add) # Random id is generated for normalized annotations - normalized_annotations[0].id = dataset_item.annotation_scene.annotations[2].id - normalized_annotations[1].id = dataset_item.annotation_scene.annotations[3].id + normalized_annotations[0].id_ = dataset_item.annotation_scene.annotations[2].id_ + normalized_annotations[1].id_ = dataset_item.annotation_scene.annotations[3].id_ assert ( dataset_item.annotation_scene.annotations == full_box_annotations + normalized_annotations @@ -796,8 +800,8 @@ def test_dataset_item_eq(self): Check DatasetItemEntity class __eq__ method Input data: - DatasetItemEntity class objects with specified "media", "annotation_scene", "roi", "metadata" and "subset" - parameters + DatasetItemEntity class objects with specified "media", "annotation_scene", "roi", "metadata", "subset" + and "ignored_labels" parameters Expected results: Test passes if value returned by __eq__ method is equal to expected @@ -805,7 +809,7 @@ def test_dataset_item_eq(self): Steps 1. Check value returned by __eq__ method for equal DatasetItemEntity objects 2. Check value returned by __eq__ method for DatasetItemEntity objects with unequal "media", "annotation_scene", - "roi" or "subset" parameters + "roi", "subset" or "ignored_labels" parameters 3. Check value returned by __eq__ method for DatasetItemEntity objects with unequal "metadata" parameters 4. Check value returned by __eq__ method for DatasetItemEntity object compared to different type object """ @@ -813,12 +817,14 @@ def test_dataset_item_eq(self): annotation_scene = DatasetItemParameters().annotations_entity() roi = DatasetItemParameters().roi() metadata = DatasetItemParameters.metadata() + ignored_labels = DatasetItemParameters.labels()[:1] dataset_parameters = { "media": media, "annotation_scene": annotation_scene, "roi": roi, "metadata": metadata, "subset": Subset.TESTING, + "ignored_labels": ignored_labels, } dataset_item = DatasetItemEntity(**dataset_parameters) # Checking value returned by __eq__ method for equal DatasetItemEntity objects @@ -827,11 +833,13 @@ def test_dataset_item_eq(self): # Checking inequality of DatasetItemEntity objects with unequal initialization parameters unequal_annotation_scene = DatasetItemParameters().annotations_entity() unequal_annotation_scene.annotations.pop(0) + unequal_ignored_labels = DatasetItemParameters.labels()[1:] unequal_values = [ ("media", DatasetItemParameters.generate_random_image()), ("annotation_scene", unequal_annotation_scene), ("roi", None), ("subset", Subset.VALIDATION), + ("ignored_labels", unequal_ignored_labels), ] for key, value in unequal_values: unequal_parameters = dict(dataset_parameters) @@ -884,7 +892,7 @@ def test_dataset_item_deepcopy(self): dataset_item.annotation_scene.editor_name == copy_dataset.annotation_scene.editor_name ) - assert dataset_item.annotation_scene.id == copy_dataset.annotation_scene.id + assert dataset_item.annotation_scene.id_ == copy_dataset.annotation_scene.id_ assert dataset_item.annotation_scene.kind == copy_dataset.annotation_scene.kind assert ( dataset_item.annotation_scene.shapes == copy_dataset.annotation_scene.shapes diff --git a/ote_sdk/ote_sdk/tests/entities/test_datasets.py b/ote_sdk/ote_sdk/tests/entities/test_datasets.py index e4cead21060..c5c0522c2de 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_datasets.py +++ b/ote_sdk/ote_sdk/tests/entities/test_datasets.py @@ -454,7 +454,7 @@ def check_empty_annotations_dataset( assert actual_item.media is expected_item.media assert actual_item.annotation_scene.annotations == [] assert actual_item.annotation_scene.kind == expected_kind - assert actual_item.roi.id != expected_item.roi.id + assert actual_item.roi.id_ != expected_item.roi.id_ assert actual_item.roi.shape is expected_item.roi.shape assert actual_item.roi.get_labels() == [] assert actual_item.subset is expected_item.subset diff --git a/ote_sdk/ote_sdk/tests/entities/test_label.py b/ote_sdk/ote_sdk/tests/entities/test_label.py index fd0d9840303..886c8e6b9b2 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_label.py +++ b/ote_sdk/ote_sdk/tests/entities/test_label.py @@ -118,10 +118,10 @@ def test_label_entity(self): assert self.car.domain == label_car_new_domain assert self.car.color == label_car_new_color assert self.car.hotkey == label_car_new_hotkey - assert self.car.id == label_car_new_id + assert self.car.id_ == label_car_new_id test_label_entity_repr = [ - f"{self.car.id}", + f"{self.car.id_}", f"name={self.car.name}", f"hotkey={self.car.hotkey}", f"domain={self.car.domain}", @@ -155,7 +155,7 @@ def test_empty_label_entity(self): """ assert self.empty.hotkey == "" - assert self.empty.id == ID() + assert self.empty.id_ == ID() assert type(self.empty.color) == Color @pytest.mark.priority_medium @@ -177,6 +177,6 @@ def test_label_comparison(self): 2. Check the processing of changed id """ - self.empty.id = ID(999999999) + self.empty.id_ = ID(999999999) assert self.empty > self.car assert self.car < self.empty diff --git a/ote_sdk/ote_sdk/tests/entities/test_label_schema.py b/ote_sdk/ote_sdk/tests/entities/test_label_schema.py index bcb991ddfb9..ecd9f55fc04 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_label_schema.py +++ b/ote_sdk/ote_sdk/tests/entities/test_label_schema.py @@ -452,7 +452,8 @@ def test_label_group_initialization(self): Test passes if LabelGroup object id, labels, name and group_type attributes return expected values Steps - 1. Check id, labels, name and group_type attributes of LabelGroup object with not specified group_type parameter + 1. Check id, labels, name and group_type attributes of LabelGroup object with not specified group_type + parameter 2. Check id, labels, name and group_type attributes of LabelGroup object with not specified id parameter """ # Checking attributes of LabelGroup object with specified id and not specified group_type parameters @@ -461,7 +462,7 @@ def test_label_group_initialization(self): labels=[labels.label_0_1, labels.no_id_label, labels.label_0], id=ID("1"), ) - assert no_group_type_label_group.id == "1" + assert no_group_type_label_group.id_ == "1" # Expected ascending sorting of labels assert no_group_type_label_group.labels == [ labels.no_id_label, @@ -481,8 +482,8 @@ def test_label_group_initialization(self): group_type=LabelGroupType.EMPTY_LABEL, ) # Expected randomly generated ID object with 24 characters as "id" attribute - assert isinstance(no_id_label_group.id, ID) - assert len(no_id_label_group.id) == 24 + assert isinstance(no_id_label_group.id_, ID) + assert len(no_id_label_group.id_) == 24 # Expected ascending sorting of labels assert no_id_label_group.labels == [labels.label_0, labels.label_0_1] assert no_id_label_group.name == "ID non-specified Label Group" @@ -577,7 +578,7 @@ def test_label_group_magic_methods(self): labels=[], group_type=LabelGroupType.EMPTY_LABEL, ) - generated_id = no_labels_no_id_label_group.id + generated_id = no_labels_no_id_label_group.id_ assert repr(no_labels_no_id_label_group) == ( f"LabelGroup(id={generated_id}, name=Null labels, random id group," f" group_type=LabelGroupType.EMPTY_LABEL, labels=[])" @@ -1295,7 +1296,7 @@ def previous_vertexes(vert_id): returned_vertexes = set() for label in labels_topological_order: - previous, curent = previous_vertexes(label.id) + previous, curent = previous_vertexes(label.id_) for vertex in previous: assert vertex in returned_vertexes returned_vertexes.add(curent) @@ -1309,7 +1310,7 @@ def previous_vertexes(vert_id): labels_topological_order = label_tree.get_labels_in_topological_order() returned_vertexes = set() for label in labels_topological_order: - previous, curent = previous_vertexes(label.id) + previous, curent = previous_vertexes(label.id_) for vertex in previous: if ( curent != "3" @@ -1852,7 +1853,9 @@ def test_label_schema_get_exclusive_groups(self): id=ID("new_ex_1"), ) new_labels_group = LabelGroup( - name="New exclusive labels group", labels=[new_label], id=ID("new_ex_group") + name="New exclusive labels group", + labels=[new_label], + id=ID("new_ex_group"), ) label_schema_entity.add_group(new_labels_group) exclusive_groups.append(new_labels_group) @@ -2136,3 +2139,84 @@ def test_label_schema_from_labels(self): assert len(labels_schema_entity_groups) == 1 assert labels_schema_entity_groups[0].name == "from_label_list" assert labels_schema_entity_groups[0].labels == expected_labels + + @pytest.mark.priority_medium + @pytest.mark.unit + @pytest.mark.reqids(Requirements.REQ_1) + def test_label_schema_resolve_labels_probabilistic(self): + """ + Description: + Check LabelSchemaEntity class resolve_labels_probabilistic method + + Input data: + LabelSchemaEntity objects with specified label_tree and label_groups parameters + + Expected results: + Test passes if LabelSchemaEntity object returned by resolve_labels_probabilistic + method is equal expected + """ + label_schema = LabelSchemaEntity() + labels_1 = [ + LabelEntity( + name=f"Label {i}", + domain=Domain.CLASSIFICATION, + id=ID(f"{i}"), + color=Color(i, 200, 166), + ) + for i in range(2) + ] + labels_2 = [ + LabelEntity( + name=f"Label {i}", + domain=Domain.CLASSIFICATION, + id=ID(f"{i}"), + color=Color(i, 200, 166), + ) + for i in range(2, 4) + ] + labels_3 = [ + LabelEntity( + name=f"Label {i}", + domain=Domain.CLASSIFICATION, + id=ID(f"{i}"), + color=Color(i, 200, 166), + ) + for i in range(4, 5) + ] + group_1 = LabelGroup( + name="labels1", labels=labels_1, group_type=LabelGroupType.EXCLUSIVE + ) + label_schema.add_group(group_1) + group_2 = LabelGroup( + name="labels2", labels=labels_2, group_type=LabelGroupType.EXCLUSIVE + ) + label_schema.add_group(group_2) + + label_schema.add_group( + LabelGroup("child_labels_2", labels_3, LabelGroupType.EXCLUSIVE) + ) + label_schema.add_child(labels_2[0], labels_3[0]) + + assert 1 == len(label_schema.get_descendants(labels_2[0])) + + # supress non-maximum labels + predicted_labels = [ + ScoredLabel(labels_1[0], 0.1), + ScoredLabel(labels_1[1], 0.5), + ScoredLabel(labels_2[0], 0.2), + ScoredLabel(labels_2[1], 0.5), + ] + resloved_labels = label_schema.resolve_labels_probabilistic(predicted_labels) + assert [ + ScoredLabel(labels_1[1], 0.5), + ScoredLabel(labels_2[1], 0.5), + ] == resloved_labels + + # supress children of non-maximum labels + predicted_labels = [ + ScoredLabel(labels_2[0], 0.1), + ScoredLabel(labels_2[1], 0.5), + ScoredLabel(labels_3[0], 0.4), + ] + resloved_labels = label_schema.resolve_labels_probabilistic(predicted_labels) + assert [ScoredLabel(labels_2[1], 0.5)] == resloved_labels diff --git a/ote_sdk/ote_sdk/tests/entities/test_model.py b/ote_sdk/ote_sdk/tests/entities/test_model.py index e2e00c6d5ff..364f69083d2 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_model.py +++ b/ote_sdk/ote_sdk/tests/entities/test_model.py @@ -154,7 +154,7 @@ def test_model_configuration(self): configurable_parameters=parameters, label_schema=label_schema ) assert model_configuration.configurable_parameters == parameters - assert model_configuration.label_schema == label_schema + assert model_configuration.get_label_schema() == label_schema @pytest.mark.components(OteSdkComponent.OTE_SDK) @@ -204,7 +204,7 @@ def test_model_entity_default_values(self): train_dataset=self.dataset(), configuration=self.configuration() ) - assert model_entity.id == ID() + assert model_entity.id_ == ID() assert type(model_entity.configuration) == ModelConfiguration assert type(model_entity.creation_date) == datetime assert type(model_entity.train_dataset) == DatasetEntity diff --git a/ote_sdk/ote_sdk/tests/entities/test_resultset.py b/ote_sdk/ote_sdk/tests/entities/test_resultset.py index 80c0d345d21..d1c7cabfcc3 100644 --- a/ote_sdk/ote_sdk/tests/entities/test_resultset.py +++ b/ote_sdk/ote_sdk/tests/entities/test_resultset.py @@ -100,7 +100,7 @@ def test_resultset_entity(self): assert result_set.performance == NullPerformance() assert type(result_set.creation_date) == datetime.datetime - assert result_set.id == ID() + assert result_set.id_ == ID() assert result_set.has_score_metric() is False result_set.performance = "test_performance" @@ -112,8 +112,8 @@ def test_resultset_entity(self): assert result_set.creation_date == creation_date set_attr_id = ID(123456789) - result_set.id = set_attr_id - assert result_set.id == set_attr_id + result_set.id_ = set_attr_id + assert result_set.id_ == set_attr_id test_result_set_repr = [ f"model={result_set.model}", @@ -122,7 +122,7 @@ def test_resultset_entity(self): f"purpose={result_set.purpose}", f"performance={result_set.performance}", f"creation_date={result_set.creation_date}", - f"id={result_set.id}", + f"id={result_set.id_}", ] for i in test_result_set_repr: diff --git a/ote_sdk/ote_sdk/tests/requirements.txt b/ote_sdk/ote_sdk/tests/requirements.txt index 6194387f22b..741cc8ca291 100644 --- a/ote_sdk/ote_sdk/tests/requirements.txt +++ b/ote_sdk/ote_sdk/tests/requirements.txt @@ -5,4 +5,4 @@ pylint==2.7.3 pytest==6.2.* pytest-cov==2.11.* openmodelzoo-modelapi @ git+https://github.com/openvinotoolkit/open_model_zoo/@releases/2021/SCMVP#egg=openmodelzoo-modelapi&subdirectory=demos/common/python -openvino==2021.4.2 \ No newline at end of file +openvino==2022.1.0.dev20220302 \ No newline at end of file diff --git a/ote_sdk/ote_sdk/tests/serialization/test_id_mapper.py b/ote_sdk/ote_sdk/tests/serialization/test_id_mapper.py index dbb2c4f1424..a55c943de64 100644 --- a/ote_sdk/ote_sdk/tests/serialization/test_id_mapper.py +++ b/ote_sdk/ote_sdk/tests/serialization/test_id_mapper.py @@ -23,8 +23,8 @@ def test_serialized_representiaton(self): This test serializes ID and checks serialized representation. """ - id = ID("21434231456") - serialized_id = IDMapper.forward(id) + id_ = ID("21434231456") + serialized_id = IDMapper.forward(id_) assert serialized_id == "21434231456" @pytest.mark.priority_medium @@ -35,7 +35,7 @@ def test_serialization_deserialization(self): This test serializes ID, deserializes serialized ID and compare with original. """ - id = ID("21434231456") - serialized_id = IDMapper.forward(id) + id_ = ID("21434231456") + serialized_id = IDMapper.forward(id_) deserialized_id = IDMapper.backward(serialized_id) - assert id == deserialized_id + assert id_ == deserialized_id diff --git a/ote_sdk/ote_sdk/tests/serialization/test_label_mapper.py b/ote_sdk/ote_sdk/tests/serialization/test_label_mapper.py index a0988674db7..c5b6bd20692 100644 --- a/ote_sdk/ote_sdk/tests/serialization/test_label_mapper.py +++ b/ote_sdk/ote_sdk/tests/serialization/test_label_mapper.py @@ -136,7 +136,7 @@ def test_flat_label_schema_serialization(self): "label_tree": {"type": "tree", "directed": True, "nodes": [], "edges": []}, "label_groups": [ { - "_id": label_schema.get_groups()[0].id, + "_id": label_schema.get_groups()[0].id_, "name": "from_label_list", "label_ids": ["0", "1", "2"], "relation_type": "EXCLUSIVE", @@ -207,7 +207,7 @@ def test_label_group_serialization(self): ) serialized = LabelGroupMapper.forward(label_group) assert serialized == { - "_id": label_group.id, + "_id": label_group.id_, "name": "Test LabelGroup", "label_ids": ["0", "1", "2"], "relation_type": "EMPTY_LABEL", diff --git a/ote_sdk/ote_sdk/tests/test_helpers.py b/ote_sdk/ote_sdk/tests/test_helpers.py index 707e7fc5755..5a9facc94d9 100644 --- a/ote_sdk/ote_sdk/tests/test_helpers.py +++ b/ote_sdk/ote_sdk/tests/test_helpers.py @@ -66,7 +66,7 @@ def new_label_by_name(self, name: str, is_empty: bool = False) -> LabelEntity: label = LabelEntity( name=name, color=Color.random(), domain=self.label_domain, is_empty=is_empty ) - label.id = generate_unique_id() + label.id_ = generate_unique_id() return label def add_hierarchy( diff --git a/ote_sdk/ote_sdk/tests/usecases/evaluation/test_f_measure.py b/ote_sdk/ote_sdk/tests/usecases/evaluation/test_f_measure.py index 80ee3eca81b..5cf87aac20a 100644 --- a/ote_sdk/ote_sdk/tests/usecases/evaluation/test_f_measure.py +++ b/ote_sdk/ote_sdk/tests/usecases/evaluation/test_f_measure.py @@ -1636,8 +1636,10 @@ def check_f_measure_common_attributes(f_measure_actual): labels[1]: ScoreMetric(name="class_2", value=0.6666666666666665), labels[2]: ScoreMetric(name="class_3", value=0.6666666666666665), } - label_schema_labels = result_set.model.configuration.label_schema.get_labels( - include_empty=False + label_schema_labels = ( + result_set.model.configuration.get_label_schema().get_labels( + include_empty=False + ) ) classes = [label.name for label in label_schema_labels] boxes_pair = _FMeasureCalculator( diff --git a/ote_sdk/ote_sdk/tests/usecases/exportable_code/test_prediction_to_annotation_converter.py b/ote_sdk/ote_sdk/tests/usecases/exportable_code/test_prediction_to_annotation_converter.py index fca687932f0..d46bdb1b73e 100644 --- a/ote_sdk/ote_sdk/tests/usecases/exportable_code/test_prediction_to_annotation_converter.py +++ b/ote_sdk/ote_sdk/tests/usecases/exportable_code/test_prediction_to_annotation_converter.py @@ -1019,7 +1019,7 @@ def check_annotation(actual_annotation: Annotation, expected_labels: list): converter = AnomalyClassificationToAnnotationConverter( label_schema=label_schema ) - predictions = np.array([(0, 9, 5), (4, 8, 24)]) + predictions = np.array([24.0]) # Checking attributes of "AnnotationSceneEntity" returned by "convert_to_annotation" for "metadata" with # specified "threshold" key metadata = { diff --git a/ote_sdk/ote_sdk/usecases/evaluation/accuracy.py b/ote_sdk/ote_sdk/usecases/evaluation/accuracy.py index e62df91e38e..31536a7a045 100644 --- a/ote_sdk/ote_sdk/usecases/evaluation/accuracy.py +++ b/ote_sdk/ote_sdk/usecases/evaluation/accuracy.py @@ -229,7 +229,7 @@ def __get_gt_and_predicted_label_indices_from_resultset( pred_dataset.sort_items() # Iterate over each dataset item, and collect the labels for this item (pred and gt) - task_labels = resultset.model.configuration.label_schema.get_labels( + task_labels = resultset.model.configuration.get_label_schema().get_labels( include_empty=True ) for gt_item, pred_item in zip(gt_dataset, pred_dataset): @@ -364,12 +364,12 @@ def compute_unnormalized_confusion_matrices_from_resultset( true_label_idx, predicted_label_idx, ) = __get_gt_and_predicted_label_indices_from_resultset(resultset) - task_labels = resultset.model.configuration.label_schema.get_labels( + task_labels = resultset.model.configuration.get_label_schema().get_labels( include_empty=False ) # Confusion matrix computation - for label_group in resultset.model.configuration.label_schema.get_groups(): + for label_group in resultset.model.configuration.get_label_schema().get_groups(): matrix = __compute_unnormalized_confusion_matrices_for_label_group( true_label_idx, predicted_label_idx, label_group, task_labels ) diff --git a/ote_sdk/ote_sdk/usecases/evaluation/dice.py b/ote_sdk/ote_sdk/usecases/evaluation/dice.py index 84ebd155ab3..2502b8cb7b8 100644 --- a/ote_sdk/ote_sdk/usecases/evaluation/dice.py +++ b/ote_sdk/ote_sdk/usecases/evaluation/dice.py @@ -113,7 +113,9 @@ def __compute_dice_averaged_over_pixels( + resultset.ground_truth_dataset.get_labels() ) model_labels = set( - resultset.model.configuration.label_schema.get_labels(include_empty=False) + resultset.model.configuration.get_label_schema().get_labels( + include_empty=False + ) ) labels = sorted(resultset_labels.intersection(model_labels)) hard_predictions = [] diff --git a/ote_sdk/ote_sdk/usecases/evaluation/f_measure.py b/ote_sdk/ote_sdk/usecases/evaluation/f_measure.py index d5f39153532..d5509dfb142 100644 --- a/ote_sdk/ote_sdk/usecases/evaluation/f_measure.py +++ b/ote_sdk/ote_sdk/usecases/evaluation/f_measure.py @@ -649,7 +649,7 @@ def __init__( ground_truth_dataset.sort_items() prediction_dataset.sort_items() - labels = resultset.model.configuration.label_schema.get_labels( + labels = resultset.model.configuration.get_label_schema().get_labels( include_empty=False ) classes = [label.name for label in labels] diff --git a/ote_sdk/ote_sdk/usecases/exportable_code/demo/requirements.txt b/ote_sdk/ote_sdk/usecases/exportable_code/demo/requirements.txt index 1e8bb7ccb55..a112995e440 100644 --- a/ote_sdk/ote_sdk/usecases/exportable_code/demo/requirements.txt +++ b/ote_sdk/ote_sdk/usecases/exportable_code/demo/requirements.txt @@ -1,3 +1,3 @@ -openvino==2021.4.2 +openvino==2022.1.0.dev20220302 openmodelzoo-modelapi @ git+https://github.com/openvinotoolkit/open_model_zoo/@ef556fee2cdd92488838b49ef8939c303992d89c#egg=openmodelzoo-modelapi&subdirectory=demos/common/python -ote-sdk @ git+https://github.com/openvinotoolkit/training_extensions/@OTE_COMMIT#egg=ote-sdk&subdirectory=ote_sdk +ote-sdk @ git+https://github.com/openvinotoolkit/training_extensions/@7e949c8939ed713772b19fa6f246cdcb9bfa6e6a#egg=ote-sdk&subdirectory=ote_sdk diff --git a/ote_sdk/ote_sdk/usecases/exportable_code/prediction_to_annotation_converter.py b/ote_sdk/ote_sdk/usecases/exportable_code/prediction_to_annotation_converter.py index 08b67172898..3778ca114b1 100644 --- a/ote_sdk/ote_sdk/usecases/exportable_code/prediction_to_annotation_converter.py +++ b/ote_sdk/ote_sdk/usecases/exportable_code/prediction_to_annotation_converter.py @@ -151,6 +151,8 @@ def create_converter( converter = ClassificationToAnnotationConverter(labels) elif converter_type == Domain.ANOMALY_CLASSIFICATION: converter = AnomalyClassificationToAnnotationConverter(labels) + elif converter_type == Domain.ANOMALY_SEGMENTATION: + converter = AnomalySegmentationToAnnotationConverter(labels) elif converter_type == Domain.INSTANCE_SEGMENTATION: converter = MaskToAnnotationConverter(labels) elif converter_type == Domain.ROTATED_DETECTION: @@ -270,11 +272,10 @@ def __init__(self, label_schema: LabelSchemaEntity): def convert_to_annotation( self, predictions: np.ndarray, metadata: Dict[str, Any] ) -> AnnotationSceneEntity: - pred_score = predictions.reshape(-1).max() - pred_label = pred_score >= metadata.get("threshold", 0.5) + pred_label = predictions >= metadata.get("threshold", 0.5) label = self.anomalous_label if pred_label else self.normal_label - probability = (1 - pred_score) if pred_score < 0.5 else pred_score + probability = (1 - predictions) if predictions < 0.5 else predictions annotations = [ Annotation( @@ -287,6 +288,41 @@ def convert_to_annotation( ) +class AnomalySegmentationToAnnotationConverter(IPredictionToAnnotationConverter): + """ + Converts AnomalyClassification Predictions ModelAPI to Annotations + """ + + def __init__(self, label_schema: LabelSchemaEntity): + labels = label_schema.get_labels(include_empty=False) + self.normal_label = [label for label in labels if label.name == "Normal"][0] + self.anomalous_label = [label for label in labels if label.name == "Anomalous"][ + 0 + ] + self.label_map = {0: self.normal_label, 1: self.anomalous_label} + + def convert_to_annotation( + self, predictions: np.ndarray, metadata: Dict[str, Any] + ) -> AnnotationSceneEntity: + + pred_mask = predictions >= 0.5 + mask = pred_mask.squeeze().astype(np.uint8) + annotations = create_annotation_from_segmentation_map( + mask, predictions, self.label_map + ) + if len(annotations) == 0: + # TODO: add confidence to this label + annotations = [ + Annotation( + Rectangle.generate_full_box(), + labels=[ScoredLabel(label=self.normal_label, probability=1.0)], + ) + ] + return AnnotationSceneEntity( + kind=AnnotationSceneKind.PREDICTION, annotations=annotations + ) + + class MaskToAnnotationConverter(IPredictionToAnnotationConverter): """ Converts DetectionBox Predictions ModelAPI to Annotations diff --git a/ote_sdk/ote_sdk/usecases/exportable_code/utils.py b/ote_sdk/ote_sdk/usecases/exportable_code/utils.py deleted file mode 100644 index 98c026c1f48..00000000000 --- a/ote_sdk/ote_sdk/usecases/exportable_code/utils.py +++ /dev/null @@ -1,30 +0,0 @@ -""" -Utils for exportable code. -""" - -# Copyright (C) 2021-2022 Intel Corporation -# SPDX-License-Identifier: Apache-2.0 -# - - -def get_git_commit_hash() -> str: - """ - Retuns current git commit hash of OTE. - """ - # TODO(ikrylov): fix it - return "develop" - - -def set_proper_git_commit_hash(path: str) -> None: - """ - Replaces OTE_COMMIT by OTE git commit hash in a file. - """ - - with open(path, encoding="UTF-8") as read_file: - content = "".join(read_file) - to_replace = "OTE_COMMIT" - if to_replace not in content: - raise RuntimeError(f"There is no {to_replace} in {path}") - content = content.replace(to_replace, get_git_commit_hash()) - with open(path, "w", encoding="UTF-8") as write_file: - write_file.write(content) diff --git a/ote_sdk/requirements.txt b/ote_sdk/requirements.txt index b72ccf0209a..a0c41e14922 100644 --- a/ote_sdk/requirements.txt +++ b/ote_sdk/requirements.txt @@ -6,4 +6,4 @@ opencv-python==4.5.3.* pymongo>=3.9 omegaconf==2.1.* natsort>=6.0.0 -attrs==21.2.* +attrs>=21.2.0 diff --git a/tests/ote_cli/common.py b/tests/ote_cli/common.py index 2cef82b6396..328a763542f 100644 --- a/tests/ote_cli/common.py +++ b/tests/ote_cli/common.py @@ -17,8 +17,6 @@ import os from subprocess import run # nosec -from ote_sdk.usecases.exportable_code.utils import get_git_commit_hash - def get_template_rel_dir(template): return os.path.dirname(os.path.relpath(template.model_template_path)) @@ -87,19 +85,6 @@ def remove_ote_sdk_from_requirements(path): write_file.write(content) -def check_ote_sdk_commit_hash_in_requirements(path): - with open(path, encoding='UTF-8') as read_file: - content = [line for line in read_file if 'ote_sdk' in line] - if len(content) != 1: - raise RuntimeError(f"Invalid ote_sdk requirements (0 or more than 1 times mentioned): {path}") - - git_commit_hash = get_git_commit_hash() - if git_commit_hash in content[0]: - return True - - return False - - def ote_train_testing(template, root, ote_dir, args): work_dir, template_work_dir, _ = get_some_vars(template, root) command_line = ['ote', @@ -253,12 +238,13 @@ def ote_deploy_openvino_testing(template, root, ote_dir, args): cwd=os.path.join(deployment_dir, 'python'), env=collect_env_vars(os.path.join(deployment_dir, 'python'))).returncode == 0 - assert check_ote_sdk_commit_hash_in_requirements(os.path.join(deployment_dir, 'python', 'requirements.txt')) - # Remove ote_sdk from requirements.txt, since merge commit (that is created on CI) is not pushed to github and that's why cannot be cloned. # Install ote_sdk from local folder instead. # Install the demo_package with --no-deps since, requirements.txt has been embedded to the demo_package during creation. remove_ote_sdk_from_requirements(os.path.join(deployment_dir, 'python', 'requirements.txt')) + assert run(['python3', '-m', 'pip', 'install', 'pip', '--upgrade'], + cwd=os.path.join(deployment_dir, 'python'), + env=collect_env_vars(os.path.join(deployment_dir, 'python'))).returncode == 0 assert run(['python3', '-m', 'pip', 'install', '-e', os.path.join(os.path.dirname(__file__), '..', '..', 'ote_sdk')], cwd=os.path.join(deployment_dir, 'python'), env=collect_env_vars(os.path.join(deployment_dir, 'python'))).returncode == 0 diff --git a/tests/ote_cli/test_ote_cli_tools_anomaly_classification.py b/tests/ote_cli/test_ote_cli_tools_anomaly_classification.py index 19d0c0d93cd..7e49d819218 100644 --- a/tests/ote_cli/test_ote_cli_tools_anomaly_classification.py +++ b/tests/ote_cli/test_ote_cli_tools_anomaly_classification.py @@ -42,11 +42,11 @@ args = { - '--train-ann-file': 'data/anomaly/train.json', + '--train-ann-file': 'data/anomaly/classification/train.json', '--train-data-roots': 'data/anomaly/shapes', - '--val-ann-file': 'data/anomaly/val.json', + '--val-ann-file': 'data/anomaly/classification/val.json', '--val-data-roots': 'data/anomaly/shapes', - '--test-ann-files': 'data/anomaly/test.json', + '--test-ann-files': 'data/anomaly/classification/test.json', '--test-data-roots': 'data/anomaly/shapes', '--input': 'data/anomaly/shapes/test/hexagon', 'train_params': [], diff --git a/tests/ote_cli/test_ote_cli_tools_anomaly_segmentation.py b/tests/ote_cli/test_ote_cli_tools_anomaly_segmentation.py new file mode 100644 index 00000000000..284f3ec6c29 --- /dev/null +++ b/tests/ote_cli/test_ote_cli_tools_anomaly_segmentation.py @@ -0,0 +1,153 @@ +"""Tests for anomaly segmentation with OTE CLI""" + +# Copyright (C) 2021 Intel Corporation +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions +# and limitations under the License. + +import os +import pytest + +from ote_sdk.test_suite.e2e_test_system import e2e_pytest_component + +from ote_cli.registry import Registry +from common import ( + create_venv, + get_some_vars, + ote_demo_deployment_testing, + ote_demo_testing, + ote_demo_openvino_testing, + ote_deploy_openvino_testing, + ote_eval_deployment_testing, + ote_eval_openvino_testing, + ote_eval_testing, + ote_train_testing, + ote_export_testing, + pot_optimize_testing, + pot_eval_testing, + nncf_optimize_testing, + nncf_export_testing, + nncf_eval_testing, + nncf_eval_openvino_testing, +) + + +args = { + '--train-ann-file': 'data/anomaly/segmentation/train.json', + '--train-data-roots': 'data/anomaly/shapes', + '--val-ann-file': 'data/anomaly/segmentation/val.json', + '--val-data-roots': 'data/anomaly/shapes', + '--test-ann-files': 'data/anomaly/segmentation/test.json', + '--test-data-roots': 'data/anomaly/shapes', + '--input': 'data/anomaly/shapes/test/hexagon', + 'train_params': [], +} + +root = '/tmp/ote_cli/' +ote_dir = os.getcwd() + +templates = Registry('external').filter(task_type='ANOMALY_SEGMENTATION').templates +templates_ids = [template.model_template_id for template in templates] + + +class TestToolsAnomalySegmentation: + @e2e_pytest_component + def test_create_venv(self): + work_dir, template_work_dir, algo_backend_dir = get_some_vars(templates[0], root) + create_venv(algo_backend_dir, work_dir, template_work_dir) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_train(self, template): + ote_train_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_export(self, template): + ote_export_testing(template, root) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_eval(self, template): + ote_eval_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_eval_openvino(self, template): + ote_eval_openvino_testing(template, root, ote_dir, args, threshold=0.01) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_demo(self, template): + ote_demo_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_demo_openvino(self, template): + ote_demo_openvino_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_deploy_openvino(self, template): + ote_deploy_openvino_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_eval_deployment(self, template): + ote_eval_deployment_testing(template, root, ote_dir, args, threshold=0.01) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_ote_demo_deployment(self, template): + ote_demo_deployment_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_nncf_optimize(self, template): + if template.entrypoints.nncf is None: + pytest.skip("nncf entrypoint is none") + + nncf_optimize_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_nncf_export(self, template): + if template.entrypoints.nncf is None: + pytest.skip("nncf entrypoint is none") + + nncf_export_testing(template, root) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_nncf_eval(self, template): + if template.entrypoints.nncf is None: + pytest.skip("nncf entrypoint is none") + + nncf_eval_testing(template, root, ote_dir, args, threshold=0.001) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_nncf_eval_openvino(self, template): + if template.entrypoints.nncf is None: + pytest.skip("nncf entrypoint is none") + + nncf_eval_openvino_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_pot_optimize(self, template): + pot_optimize_testing(template, root, ote_dir, args) + + @e2e_pytest_component + @pytest.mark.parametrize("template", templates, ids=templates_ids) + def test_pot_eval(self, template): + pot_eval_testing(template, root, ote_dir, args) diff --git a/training_extensions_framework.png b/training_extensions_framework.png new file mode 100644 index 00000000000..58f5f327499 Binary files /dev/null and b/training_extensions_framework.png differ