diff --git a/Dockerfile b/Dockerfile
new file mode 100644
index 0000000..7b8067c
--- /dev/null
+++ b/Dockerfile
@@ -0,0 +1,45 @@
+FROM nvidia/cuda:12.6.3-cudnn-devel-ubuntu22.04
+
+# Install system dependencies
+
+RUN apt update \
+ && apt install --assume-yes \
+ libgl1-mesa-glx \
+ libglib2.0-0 \
+ libqt5gui5 \
+ libusb-1.0-0-dev \
+ python3 \
+ python3-pip \
+ unzip \
+ wget \
+ && apt clean
+
+
+# Install Python dependencies
+
+COPY ./requirements.txt /tmp/requirements.txt
+RUN pip3 install --no-cache-dir --requirement /tmp/requirements.txt \
+ && rm /tmp/requirements.txt
+
+
+# Install ZWO ASI SDK
+
+WORKDIR /tmp
+RUN wget --output-document=ASI_Camera_SDK.zip \
+ --output-file=/dev/null \
+ "https://drive.usercontent.google.com/download?id=1iykpJYbkUx5H9aESjtk6ac--Bpflq-HR&export=download&authuser=1&confirm=t"\
+ && unzip /tmp/ASI_Camera_SDK.zip \
+ && tar --extract --verbose --bzip2 --file ASI_Camera_SDK/ASI_linux_mac_SDK_V*.tar.bz2 \
+ && rm --recursive ASI_Camera_SDK.zip ASI_Camera_SDK \
+ && install ASI_linux_mac_SDK_V*/lib/asi.rules /lib/udev/rules.d \
+ && cp ASI_linux_mac_SDK_V*/lib/x64/* /usr/lib64/
+
+ENV ZWO_ASI_LIB=/usr/lib64/libASICamera2.so
+
+
+## Copy the rest of the application
+#
+#COPY . /app
+#WORKDIR /app
+#
+#ENTRYPOINT ["python3", "main.py"]
diff --git a/README.md b/README.md
index de38251..c085e98 100644
--- a/README.md
+++ b/README.md
@@ -1,27 +1,87 @@
# TeideSat Satellite Tracking for the Optical Ground Station
-The TeideSat CubeSat tracking program offers an API that enables real-time monitoring from any location on Earth.
+This program is part of the TeideSat project, developed by a student's association from the Canary Islands' universities. The main objective of the project is to design and build a nano-satellite to be launched into space to perform scientific experiments.
-Utilizing computer vision algorithms, this program provides the satellite’s ephemeris, which includes the elevation angle and azimuth angle. These values, obtained in real-time from video camera frames and TLE coordinates, allow for accurate and up-to-date tracking of the TeideSat CubeSat.
+This program is used to track the satellite using an Optical Ground Station (OGS), composed by a main telescope and a guider telescope. The guider telescope has a camera attached to it which is continuously recording the night sky. This video stream is feed from the OGS to this program to detect all the light sources on each frame, characterize them and obtain which of them are from moving satellites to finally track them with the main telescope.
-## Installation:
-1. Clone this repo:
+## Installation and usage:
+ 1. Clone this repo:
+ ```
+ $ git clone https://github.com/Teidesat/teidesat-cubesat-tracker.git
+ $ cd teidesat-cubesat-tracker
+ ```
+
+ 2. Build the docker image:
+ ```
+ $ docker build -f Dockerfile -t teidesat-cubesat-tracker:latest .
+ ```
+
+ 3. Run the docker container:
+ ```
+ $ docker compose run --rm teidesat-cubesat-tracker
+ ```
+
+## Development installation:
+
+ 1. Clone this repo:
+ ```
+ $ git clone https://github.com/Teidesat/teidesat-cubesat-tracker.git
+ $ cd teidesat-cubesat-tracker
+ ```
+
+ 2. Create a virtual environment:
+ ```
+ $ python3 -m venv venv
+ $ source venv/bin/activate
+ ```
+
+ 3. Install the dependencies:
+ ```
+ $ pip install -r requirements.txt
+ ```
+
+ 4. Run the code:
+ ```
+ $ python3 ./main.py
+ ```
+ or
+ ```
+ $ chmod +x ./main.py
+ $ ./main.py
+ ```
+
+### Run the code tests:
```
- $ git clone https://github.com/Teidesat/teidesat-cubesat-tracker.git
+ $ python3 -m unittest discover -s test
```
-
-2. Install dependencies:
+ or
```
- $ cd teidesat-cubesat-tracker
- $ pip install -r requirements.txt
+ $ coverage run --branch --omit=config*,*init*,test* -m unittest && echo '' && coverage report -m && coverage erase
```
-## Usage:
-```
-$ python3 ./main.py
-```
-or
-```
-$ chmod +x ./main.py
-$ ./main.py
-```
+### Stars detection with the neural network model:
+
+The neural network model used to detect stars in the video stream is a pre-trained model based on image segmentation. More information on the training process and the model architecture can be found at its dedicated GitHub repository: https://github.com/Teidesat/intelligent-sky-objects-detector
+
+To use this detection mode, follow these steps:
+
+ 1. Download the trained neural network model from the following link:
+ ```
+ https://drive.google.com/drive/folders/1kO81C8dctVbbpROEhiE7BLP7iTWPYEi1?usp=sharing
+ ```
+
+ 2. Create a folder named 'trained-models' and move the downloaded model to it:
+ ```
+ $ mkdir /path/to/trained-models
+ $ mv path/to/downloaded/model /path/to/trained-models/
+ ```
+
+ 3. Create a '.env' file with the following content:
+ ```
+ TRAINED_MODELS_PATH=/path/to/trained-models
+ ```
+
+ 4. Verify that the detection mode is set to 'NEURAL_NETWORK' in the 'constants.py' file:
+ ```
+ STAR_DETECTION_MODE = "NEURAL_NETWORK"
+ ```
diff --git a/constants.py b/constants.py
index 98ea226..2d9ef31 100644
--- a/constants.py
+++ b/constants.py
@@ -7,42 +7,164 @@
from datetime import datetime
from pathlib import Path
-# * Constants
-STAR_DETECTOR_THRESHOLD = 50
-FAST = True
-MIN_PRUNE_DISTANCE = 20.0
-SAT_DESIRED_BLINKING_FREQ = 15.0
-MOVEMENT_THRESHOLD = 3.0
-PX_SENSITIVITY = 8
+##################
+# Input settings #
+##################
+
+# Type of the input stream to use, the supported types are:
+# - "VIDEO_FILE" for pre-recorded videos.
+# - "WEBCAM" for USB webcams detected by OpenCV.
+# - "ZWOASI" for ZWO ASI cameras detected by the ZWO ASI SDK.
+SOURCE_TYPE = "VIDEO_FILE"
+
+# If using a camera as input source, index of the camera to use.
+# The default camera value is 0.
+CAMERA_INDEX = 0
-PATH_FRAME = Path("./data/images/original.jpg")
-PATH_VIDEO = Path("./data/videos/video4.mp4")
-PATH_SAT_LOG = Path("./data/logs/satellite_log.csv")
+# If using a video file as input source, path to the video file to use.
+PATH_INPUT_VIDEO = Path("./data/videos/video4.mp4")
-RGB_IMAGE = True
-VIDEO_FROM_CAMERA = False
+# Default frames per second of the input stream (only used if it couldn't be retrieved
+# from the input source's information).
VIDEO_FPS = 60.0
+
+###################
+# Output settings #
+###################
+
+# If true, the program will show the processed video in a window.
SHOW_VIDEO_RESULT = True
+
+# If true, the detected satellite will be centered in the video.
+SIMULATE_TRACKING = True
+
+# If true, the program will draw a circle around the detected stars.
+MARK_DETECTED_STARS = False
+# If true, the program will draw a circle around the tracked stars.
+MARK_TRACKED_STARS = True
+# If true, the program will draw a circle around the shooting stars.
+MARK_SHOOTING_STARS = True
+# If true, the program will draw a circle around the detected satellite.
+MARK_SATELLITE = True
+# If true, the program will draw a line representing the movement vector of the
+# shooting stars and the satellite.
+MARK_MOVEMENT_VECTOR = True
+# If true, the program will draw a circle around the next expected position of the
+# shooting stars and the satellite.
+MARK_NEXT_EXPECTED_POSITION = True
+# If true, the program will draw a circle around the last predicted position of the
+# shooting stars and the satellite.
+MARK_LAST_PREDICTED_POSITION = True
+
+# If true, the program will draw the tracked stars in different colors.
COLORIZED_TRACKED_STARS = False
-OUTPUT_VIDEO_TO_FILE = True
-PATH_OUTPUT_VIDEO = Path(
+
+# Default color of the circle to draw around each star.
+MARK_POSITION_DEFAULT_COLOR = (0, 0, 100)
+# Color of the circle to draw around the shooting stars.
+MARK_SHOOTING_STAR_COLOR = (0, 200, 200)
+# Color of the circle to draw around the detected satellite.
+MARK_SATELLITE_COLOR = (0, 200, 0)
+# Color of the circle to draw around the next expected position of a moving object.
+MARK_NEXT_EXPECTED_POSITION_COLOR = (200, 200, 0)
+# Color of the circle to draw around the last predicted position of a moving object.
+MARK_LAST_PREDICTED_POSITION_COLOR = (200, 0, 200)
+# Default color of the line to draw the movement vector of each star.
+MARK_MOVEMENT_VECTOR_COLOR = (200, 200, 0)
+# Radius of the circle to draw around each star.
+MARK_RADIUS = 8
+# Thickness of the line to draw around each star.
+MARK_THICKNESS = 2
+
+# If true, the program will dump the input stream frames into a video file.
+OUTPUT_RAW_VIDEO_TO_FILE = True
+# Path to the file in which the input stream frames will be dumped.
+PATH_OUTPUT_RAW_VIDEO = Path(
+ "./data/videos/video_output_"
+ + datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
+ + "_raw.mp4",
+)
+
+# If true, the program will dump the processed frames into a video file.
+OUTPUT_PROCESSED_VIDEO_TO_FILE = True
+# Path to the file in which the processed frames will be dumped.
+PATH_OUTPUT_PROCESSED_VIDEO = Path(
"./data/videos/video_output_"
+ datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
- + ".mp4"
+ + "_processed.mp4",
+)
+
+
+# If true, the program will log the detected satellite data into a file.
+OUTPUT_SAT_LOG_TO_FILE = True
+# Path to the file in which the satellite data will be logged.
+PATH_OUTPUT_SAT_LOG = Path(
+ "./data/logs/satellite_log_"
+ + datetime.now().strftime("%Y-%m-%d_%H-%M-%S")
+ + ".csv",
)
+
+#################
+# Star settings #
+#################
+
+# Type of the star detection mode to use, the supported types are:
+# - "OPEN_CV" for the OpenCV star detector.
+# - "NEURAL_NETWORK" for the neural network star detector.
+STAR_DETECTION_MODE = "NEURAL_NETWORK"
+
+# Path to the neural network model to use as the star detector.
+NEURAL_NETWORK_MODEL_PATH = Path("/app/trained-models/model-2024_12_10-16_49_43.keras")
+
+# Minimum brightness to be considered a star.
+STAR_DETECTOR_THRESHOLD = 50
+
+# If true, the program will prune close points to avoid duplicate stars
+# else, it will keep all the detected stars.
+# Note: If enabled, the performance of the program could be highly reduced.
+PRUNE_CLOSE_POINTS = False
+# Minimum distance between two points to be considered different stars.
+MIN_PRUNE_DISTANCE = 20.0
+
+# Number of frames a star will be stored without being detected.
DEFAULT_LEFT_LIFETIME = 10
-DEFAULT_VECTOR = (0.0, 0.0)
+# Maximum number of frames to store as the history of a star.
+MAX_HISTORY_LENGTH = 20
+
+################################
+# Satellite detection settings #
+################################
+
+# Desired blinking frequency of the satellite on detection phase.
+SAT_DESIRED_BLINKING_FREQ = 15.0
+# Minimum blinking difference to consider a star as the satellite.
+FREQUENCY_THRESHOLD = 3.0
+# Minimum confidence to consider a star as the satellite based on its blinking
+# frequency and relative movement velocity.
MIN_DETECTION_CONFIDENCE = 20
+
+########################################
+# Movement vector computation settings #
+########################################
+
+# Default movement vector of a star.
+DEFAULT_VECTOR = (0.0, 0.0)
+# Minimum distance to consider that a star has moved.
+MOVEMENT_THRESHOLD = 3.0
+# Minimum number of frames to compute the movement vector of a star.
MIN_HISTORY_LENGTH = 10
-MAX_HISTORY_LENGTH = 20
+# If true, the program will remove outliers when computing the average movement
+# vector of a star.
REMOVE_OUTLIERS = True
+# Threshold to consider a movement vector as an outlier.
MAX_OUTLIER_THRESHOLD = 1.5
+# Maximum distance difference to consider a movement vector as an outlier.
MAX_MOVE_DISTANCE = 10.0
-
-FREQUENCY_THRESHOLD = 3.0
+# Method to compute the average movement vector of a star.
+MOVEMENT_VECTOR_COMPUTATION_METHOD = "mean"
diff --git a/data/logs/satellite_log.csv b/data/logs/satellite_log.csv
deleted file mode 100644
index fe21418..0000000
--- a/data/logs/satellite_log.csv
+++ /dev/null
@@ -1,195 +0,0 @@
-id; last_times_detected; lifetime; left_lifetime; detection_confidence; blinking_freq; movement_vector; frames_since_last_detection; last_detected_position; expected_position; last_positions;
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 28; 9; 21; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (993.0, 495.0); (988, 498); [(1036.0, 470.0), None, (1031.0, 472.0), None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 29; 10; 22; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (989.0, 498.0); (987, 499); [None, (1031.0, 472.0), None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 30; 9; 23; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (989.0, 498.0); (984, 501); [(1031.0, 472.0), None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 31; 10; 24; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (984, 501); (982, 502); [None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 32; 9; 25; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (984, 501); (979, 504); [(1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 33; 10; 26; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (979, 504); (977, 505); [None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 34; 9; 27; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (979, 504); (974, 507); [(1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 35; 10; 28; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (974.0, 506.0); (972, 507); [None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 36; 9; 29; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (974.0, 506.0); (969, 509); [(1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 37; 10; 30; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (970.0, 510.0); (968, 511); [None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1]; 38; 10; 31; 16.5; (-2.3333333333333335, 1.4444444444444444); 1; (970.0, 511.0); (968, 512); [(1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0)];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]; 39; 10; 32; 16.5; (-2.3125, 1.4375); 1; (964.0, 512.0); (962, 513); [None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]; 40; 9; 33; 16.5; (-2.3125, 1.4375); 2; (964.0, 512.0); (959, 515); [(1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]; 41; 10; 34; 16.5; (-2.3125, 1.375); 1; (960.0, 514.0); (958, 515); [None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1]; 42; 10; 32; 18.0; (-2.2941176470588234, 1.411764705882353); 1; (958.0, 516.0); (956, 517); [(1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0)];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1]; 43; 10; 30; 18.0; (-2.3125, 1.4375); 1; (955.0, 518.0); (953, 519); [None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0]; 44; 9; 28; 18.0; (-2.3125, 1.4375); 2; (955.0, 518.0); (950, 521); [(998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1]; 45; 10; 26; 18.0; (-2.3125, 1.5); 1; (950, 521); (948, 522); [None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None, (950, 521)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0]; 46; 9; 24; 18.0; (-2.3125, 1.5); 2; (950, 521); (945, 524); [(993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None, (950, 521), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1]; 47; 10; 22; 18.0; (-2.375, 1.5); 1; (945, 524); (943, 526); [None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None, (950, 521), None, (945, 524)];
-5317; [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 136; 9; 21; 13.5; (-2.4375, 1.5); 2; (732, 655); (727, 658); [None, None, (771, 631), None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 137; 10; 22; 15.0; (-2.4444444444444446, 1.5); 1; (727, 658); (725, 660); [None, (771, 631), None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 138; 9; 23; 15.0; (-2.4444444444444446, 1.5); 2; (727, 658); (722, 661); [(771, 631), None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 139; 10; 24; 15.0; (-2.4444444444444446, 1.5); 1; (722, 661); (720, 662); [None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 140; 9; 25; 15.0; (-2.4444444444444446, 1.5); 2; (722, 661); (717, 664); [(766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 141; 10; 26; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (719.0, 663.0); (717, 664); [None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 142; 9; 27; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (719.0, 663.0); (714, 666); [(761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 143; 10; 28; 15.0; (-2.388888888888889, 1.4444444444444444); 1; (714, 666); (712, 667); [None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 144; 9; 29; 15.0; (-2.388888888888889, 1.4444444444444444); 2; (714, 666); (709, 669); [(757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 145; 10; 30; 15.0; (-2.388888888888889, 1.5555555555555556); 1; (709.0, 671.0); (707, 673); [None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 146; 9; 31; 15.0; (-2.388888888888889, 1.5555555555555556); 2; (709.0, 671.0); (704, 674); [(752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 147; 10; 32; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (703.0, 674.0); (701, 676); [None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 148; 9; 33; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (703.0, 674.0); (698, 677); [(747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 149; 10; 34; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (698, 677); (696, 679); [None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1]; 150; 10; 35; 16.5; (-2.3684210526315788, 1.5263157894736843); 1; (697.0, 678.0); (695, 680); [(742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0)];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]; 151; 10; 36; 16.5; (-2.4375, 1.5625); 1; (693.0, 680.0); (691, 682); [None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]; 152; 9; 37; 16.5; (-2.4375, 1.5625); 2; (693.0, 680.0); (688, 683); [(737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]; 153; 10; 38; 16.5; (-2.4375, 1.5625); 1; (688, 683); (686, 685); [None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0]; 154; 9; 39; 16.5; (-2.4375, 1.5625); 2; (688, 683); (683, 686); [(732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1]; 155; 10; 40; 16.5; (-2.2941176470588234, 1.5294117647058822); 1; (684.0, 686.0); (682, 688); [None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0]; 156; 9; 41; 16.5; (-2.2941176470588234, 1.5294117647058822); 2; (684.0, 686.0); (679, 689); [(727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1]; 157; 10; 42; 16.5; (-2.2941176470588234, 1.5294117647058822); 1; (679, 689); (677, 691); [None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0]; 158; 9; 43; 16.5; (-2.2941176470588234, 1.5294117647058822); 2; (679, 689); (674, 692); [(722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 159; 10; 44; 16.5; (-2.6470588235294117, 1.6470588235294117); 1; (673.0, 692.0); (670, 694); [None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 160; 9; 45; 16.5; (-2.6470588235294117, 1.6470588235294117); 2; (673.0, 692.0); (668, 695); [(719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 161; 10; 46; 16.5; (-2.5, 1.625); 1; (669.0, 695.0); (666, 697); [None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 162; 9; 47; 16.5; (-2.5, 1.625); 2; (669.0, 695.0); (664, 698); [(714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None];
-5317; [0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 163; 10; 48; 16.5; (-2.5, 1.5); 1; (664, 698); (662, 700); [None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698)];
-5317; [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 164; 9; 49; 16.5; (-2.5, 1.5); 2; (664, 698); (659, 701); [(709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None];
-5317; [0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 165; 10; 50; 16.5; (-2.4375, 1.5625); 1; (659.0, 702.0); (657, 704); [None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0)];
-5317; [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 166; 9; 51; 16.5; (-2.4375, 1.5625); 2; (659.0, 702.0); (654, 705); [(703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None];
-5317; [0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 167; 10; 52; 16.5; (-2.4375, 1.5625); 1; (654, 705); (652, 707); [None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705)];
-5317; [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 168; 9; 53; 16.5; (-2.4375, 1.5625); 2; (654, 705); (649, 708); [(698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None];
-5317; [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 169; 10; 54; 16.5; (-2.4444444444444446, 1.5555555555555556); 1; (649, 708); (647, 710); [(697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 170; 9; 55; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (649, 708); (644, 711); [(693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 171; 10; 56; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (644, 711); (642, 713); [None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 172; 9; 57; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (644, 711); (639, 714); [(688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 173; 10; 58; 15.0; (-2.5, 1.5555555555555556); 1; (639, 714); (636, 716); [None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 174; 9; 59; 15.0; (-2.5, 1.5555555555555556); 2; (639, 714); (634, 717); [(684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 175; 10; 60; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (635.0, 718.0); (633, 720); [None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 176; 9; 61; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (635.0, 718.0); (630, 721); [(679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 177; 10; 62; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (629.0, 720.0); (627, 722); [None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 178; 9; 63; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (629.0, 720.0); (624, 723); [(673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 179; 10; 64; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (625.0, 724.0); (623, 726); [None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 180; 9; 65; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (625.0, 724.0); (620, 727); [(669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 181; 10; 66; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (620, 727); (618, 729); [None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 182; 9; 67; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (620, 727); (615, 730); [(664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 183; 10; 68; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (615, 730); (613, 732); [None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 184; 9; 69; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (615, 730); (610, 733); [(659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 185; 10; 70; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (610, 733); (608, 735); [None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 186; 9; 71; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (610, 733); (605, 736); [(654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 187; 10; 72; 15.0; (-2.3333333333333335, 1.5); 1; (607.0, 735.0); (605, 736); [None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 188; 9; 73; 15.0; (-2.3333333333333335, 1.5); 2; (607.0, 735.0); (602, 738); [(649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 189; 10; 74; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (602.0, 737.0); (600, 738); [None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 190; 9; 75; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (602.0, 737.0); (597, 740); [(644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 191; 10; 76; 15.0; (-2.2777777777777777, 1.5); 1; (598.0, 741.0); (596, 742); [None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 192; 9; 77; 15.0; (-2.2777777777777777, 1.5); 2; (598.0, 741.0); (593, 744); [(639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 193; 10; 78; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (592.0, 743.0); (590, 744); [None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 194; 9; 79; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (592.0, 743.0); (587, 746); [(635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 195; 10; 80; 15.0; (-2.2777777777777777, 1.5); 1; (588.0, 747.0); (586, 748); [None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 196; 9; 81; 15.0; (-2.2777777777777777, 1.5); 2; (588.0, 747.0); (583, 750); [(629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 197; 10; 82; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (583, 750); (581, 751); [None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 198; 9; 83; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (583, 750); (578, 753); [(625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 199; 10; 84; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (578, 753); (576, 754); [None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 200; 9; 85; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (578, 753); (573, 756); [(620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 201; 10; 86; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (573, 756); (571, 757); [None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 202; 9; 87; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (573, 756); (568, 759); [(615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 203; 10; 88; 15.0; (-2.3333333333333335, 1.5); 1; (568.0, 760.0); (566, 762); [None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 204; 9; 89; 15.0; (-2.3333333333333335, 1.5); 2; (568.0, 760.0); (563, 763); [(610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 205; 10; 90; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (563, 763); (561, 765); [None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 206; 9; 91; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (563, 763); (558, 766); [(607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 207; 10; 92; 15.0; (-2.388888888888889, 1.6111111111111112); 1; (559.0, 766.0); (557, 768); [None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 208; 9; 93; 15.0; (-2.388888888888889, 1.6111111111111112); 2; (559.0, 766.0); (554, 769); [(602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 209; 10; 94; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (554.0, 770.0); (552, 772); [None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 210; 9; 95; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (554.0, 770.0); (549, 773); [(598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 211; 10; 96; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (548.0, 772.0); (546, 774); [None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 212; 9; 97; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (548.0, 772.0); (543, 775); [(592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 213; 10; 98; 15.0; (-2.5, 1.5555555555555556); 1; (543, 775); (540, 777); [None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1]; 214; 10; 99; 16.5; (-2.5, 1.5555555555555556); 1; (543.0, 774.0); (540, 776); [(588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0)];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]; 215; 10; 100; 16.5; (-2.5, 1.5625); 1; (533.0, 778.0); (530, 780); [None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]; 216; 9; 101; 16.5; (-2.5, 1.5625); 2; (533.0, 778.0); (528, 781); [(583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0]; 217; 8; 102; 15.0; (-2.5, 1.5714285714285714); 3; (533.0, 778.0); (526, 783); [None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0]; 218; 7; 103; 15.0; (-2.5, 1.5714285714285714); 4; (533.0, 778.0); (523, 784); [(578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1]; 219; 10; 104; 15.0; (-2.125, 1.625); 1; (529.0, 785.0); (527, 787); [None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1]; 220; 10; 105; 16.5; (-2.0588235294117645, 1.588235294117647); 1; (528.0, 786.0); (526, 788); [(573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0)];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]; 221; 10; 106; 16.5; (-2.0, 1.5333333333333334); 1; (525.0, 786.0); (523, 788); [None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0]; 222; 9; 107; 16.5; (-2.0, 1.5333333333333334); 2; (525.0, 786.0); (521, 789); [(568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1]; 223; 10; 108; 16.5; (-2.142857142857143, 1.7857142857142858); 1; (519.0, 792.0); (517, 794); [None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0]; 224; 9; 109; 16.5; (-2.142857142857143, 1.7857142857142858); 2; (519.0, 792.0); (515, 796); [(563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1]; 225; 10; 110; 16.5; (-2.7, 1.8); 1; (514.0, 795.0); (511, 797); [None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]; 226; 9; 111; 16.5; (-2.7, 1.8); 2; (514.0, 795.0); (509, 799); [(559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None];
-5317; [0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1]; 227; 10; 112; 16.5; (-2.625, 1.375); 1; (509.0, 798.0); (506, 799); [None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0)];
-5317; [1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0]; 228; 9; 113; 16.5; (-2.625, 1.375); 2; (509.0, 798.0); (504, 801); [(554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None];
-5317; [0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 229; 8; 114; 15.0; (-2.0833333333333335, 1.8333333333333333); 3; (509.0, 798.0); (503, 804); [None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None];
-5317; [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 230; 7; 115; 15.0; (-2.0833333333333335, 1.8333333333333333); 4; (509.0, 798.0); (501, 805); [(548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None];
-5317; [0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]; 231; 6; 116; 13.5; (-2.0, 1.9); 5; (509.0, 798.0); (499, 808); [None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None];
-5317; [1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]; 232; 5; 117; 13.5; (-2.0, 1.9); 6; (509.0, 798.0); (497, 809); [(543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None];
-5317; [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]; 233; 10; 118; 13.5; (-2.5833333333333335, 1.8333333333333337); 1; (494.0, 808.0); (491, 810); [(543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0)];
-5317; [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0]; 234; 9; 116; 12.0; (-2.0, 1.6000000000000003); 2; (494.0, 808.0); (490, 811); [(533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None];
-5317; [0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]; 235; 10; 114; 12.0; (-2.4166666666666665, 1.4166666666666667); 1; (490.0, 809.0); (488, 810); [None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0)];
-5317; [0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0]; 236; 9; 112; 12.0; (-2.4166666666666665, 1.4166666666666667); 2; (490.0, 809.0); (485, 812); [None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None];
-5317; [0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0]; 237; 8; 110; 12.0; (-2.4166666666666665, 1.4166666666666667); 3; (490.0, 809.0); (483, 813); [None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None];
-5317; [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0]; 238; 7; 108; 12.0; (-2.4166666666666665, 1.4166666666666667); 4; (490.0, 809.0); (480, 815); [(529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None];
-5317; [1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0]; 239; 6; 106; 10.5; (-2.4166666666666665, 1.4166666666666667); 5; (490.0, 809.0); (478, 816); [(528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]; 240; 5; 104; 9.0; (-2.5, 1.642857142857143); 6; (490.0, 809.0); (475, 819); [(525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None];
-5317; [0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]; 241; 10; 102; 9.0; (-2.3888888888888893, 1.5000000000000004); 1; (476.0, 819.0); (474, 820); [None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0)];
-5317; [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0]; 242; 9; 100; 9.0; (-2.3888888888888893, 1.5000000000000004); 2; (476.0, 819.0); (471, 822); [(519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None];
-5317; [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]; 243; 10; 98; 9.0; (-2.388888888888889, 1.5000000000000002); 1; (471, 822); (469, 824); [None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822)];
-5317; [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0]; 244; 9; 96; 9.0; (-2.388888888888889, 1.5000000000000002); 2; (471, 822); (466, 825); [(514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None];
-5317; [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1]; 245; 10; 94; 9.0; (-2.4999999999999996, 1.6111111111111112); 1; (464.0, 827.0); (462, 829); [None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0)];
-5317; [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0]; 246; 9; 92; 9.0; (-2.4999999999999996, 1.6111111111111112); 2; (464.0, 827.0); (459, 830); [(509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None];
-5317; [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]; 247; 10; 90; 9.0; (-2.4285714285714284, 1.6428571428571428); 1; (460.0, 831.0); (458, 833); [None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0)];
-5317; [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 248; 9; 88; 9.0; (-2.4285714285714284, 1.6428571428571428); 2; (460.0, 831.0); (455, 834); [None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None];
-5317; [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 249; 10; 86; 10.5; (-2.4375, 1.625); 1; (455, 834); (453, 836); [None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834)];
-5317; [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 250; 9; 84; 10.5; (-2.4375, 1.625); 2; (455, 834); (450, 837); [None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None];
-5317; [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 251; 8; 82; 10.5; (-2.4375, 1.625); 3; (455, 834); (448, 839); [None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None];
-5317; [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 252; 7; 80; 10.5; (-2.4375, 1.625); 4; (455, 834); (445, 840); [(494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None];
-5317; [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1]; 253; 10; 78; 10.5; (-2.388888888888889, 1.7222222222222223); 1; (447.0, 840.0); (445, 842); [None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0)];
-5317; [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0]; 254; 9; 76; 10.5; (-2.388888888888889, 1.7222222222222223); 2; (447.0, 840.0); (442, 843); [(490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None];
-5317; [0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]; 255; 10; 74; 10.5; (-2.5714285714285716, 1.5714285714285714); 1; (440.0, 841.0); (437, 843); [None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0)];
-5317; [0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]; 256; 9; 72; 10.5; (-2.5714285714285716, 1.5714285714285714); 2; (440.0, 841.0); (435, 844); [None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None];
-5317; [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1]; 257; 10; 70; 12.0; (-2.5625, 1.5625); 1; (435, 844); (432, 846); [None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844)];
-5317; [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0]; 258; 9; 68; 12.0; (-2.5625, 1.5625); 2; (435, 844); (430, 847); [None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0]; 259; 8; 66; 12.0; (-2.5625, 1.5625); 3; (435, 844); (427, 849); [None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 260; 7; 64; 12.0; (-2.5625, 1.5625); 4; (435, 844); (425, 850); [(476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None];
-5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1]; 261; 10; 62; 12.0; (-2.5, 1.6111111111111112); 1; (426.0, 851.0); (424, 853); [None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0)];
-5317; [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0]; 262; 9; 60; 12.0; (-2.5, 1.6111111111111112); 2; (426.0, 851.0); (421, 854); [(471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]; 263; 10; 58; 12.0; (-2.388888888888889, 1.5); 1; (421, 854); (419, 856); [None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854)];
-5317; [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]; 264; 9; 56; 12.0; (-2.388888888888889, 1.5); 2; (421, 854); (416, 857); [(464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None];
-5317; [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1]; 265; 10; 54; 12.0; (-2.4444444444444446, 1.4444444444444444); 1; (416, 857); (414, 858); [None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857)];
-5317; [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0]; 266; 9; 52; 12.0; (-2.4444444444444446, 1.4444444444444444); 2; (416, 857); (411, 860); [(460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None];
-5317; [0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]; 267; 10; 50; 12.0; (-2.4444444444444446, 1.5); 1; (411.0, 861.0); (409, 862); [None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0)];
-5317; [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 268; 9; 48; 12.0; (-2.4444444444444446, 1.5); 2; (411.0, 861.0); (406, 864); [(455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None];
-5317; [0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 269; 10; 46; 12.0; (-2.5625, 1.5); 1; (406, 864); (403, 866); [None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864)];
-5317; [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 270; 9; 44; 12.0; (-2.5625, 1.5); 2; (406, 864); (401, 867); [None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None];
-5317; [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 271; 10; 45; 13.5; (-2.5555555555555554, 1.5); 1; (401, 867); (398, 868); [None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None, (401, 867)];
-5317; [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 272; 9; 46; 13.5; (-2.5555555555555554, 1.5); 2; (401, 867); (396, 870); [(447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None, (401, 867), None];
-5317; [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 273; 8; 44; 12.0; (-2.4375, 1.625); 3; (401, 867); (394, 872); [None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None, (401, 867), None, None];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0]; 50; 9; 43; 16.5; (-2.5, 1.6111111111111112); 2; (395, 872); (390, 875); [(440.0, 843.0), None, (435.0, 847.0), None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 51; 10; 44; 16.5; (-2.4444444444444446, 1.5); 1; (391.0, 874.0); (389, 876); [None, (435.0, 847.0), None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 52; 9; 45; 16.5; (-2.4444444444444446, 1.5); 2; (391.0, 874.0); (386, 877); [(435.0, 847.0), None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 53; 10; 46; 16.5; (-2.4444444444444446, 1.6666666666666667); 1; (386.0, 880.0); (384, 882); [None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 54; 9; 47; 16.5; (-2.4444444444444446, 1.6666666666666667); 2; (386.0, 880.0); (381, 883); [(430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None];
-6204; [0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 55; 10; 48; 16.5; (-2.388888888888889, 1.6666666666666667); 1; (382.0, 883.0); (380, 885); [None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0)];
-6204; [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 56; 9; 49; 16.5; (-2.388888888888889, 1.6666666666666667); 2; (382.0, 883.0); (377, 886); [(425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None];
-6204; [0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 57; 10; 50; 16.5; (-2.5, 1.6111111111111112); 1; (375.0, 885.0); (372, 887); [None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0)];
-6204; [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 58; 9; 51; 16.5; (-2.5, 1.6111111111111112); 2; (375.0, 885.0); (370, 888); [(420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None];
-6204; [0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 59; 10; 52; 16.5; (-2.5, 1.6666666666666667); 1; (370.0, 889.0); (368, 891); [None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0)];
-6204; [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 60; 9; 53; 16.5; (-2.5, 1.6666666666666667); 2; (370.0, 889.0); (365, 892); [(415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None];
-6204; [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 61; 10; 54; 16.5; (-2.473684210526316, 1.631578947368421); 1; (365, 892); (363, 894); [(412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 62; 9; 55; 15.0; (-2.5, 1.6111111111111112); 2; (365, 892); (360, 895); [(410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 63; 10; 56; 15.0; (-2.5, 1.6666666666666667); 1; (360.0, 896.0); (358, 898); [None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 64; 9; 57; 15.0; (-2.5, 1.6666666666666667); 2; (360.0, 896.0); (355, 899); [(405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 65; 10; 58; 15.0; (-2.5, 1.6666666666666667); 1; (355, 899); (352, 901); [None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 66; 9; 59; 15.0; (-2.5, 1.6666666666666667); 2; (355, 899); (350, 902); [(400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 67; 10; 60; 15.0; (-2.5, 1.6666666666666667); 1; (350, 902); (348, 904); [None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 68; 9; 61; 15.0; (-2.5, 1.6666666666666667); 2; (350, 902); (345, 905); [(395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 69; 10; 62; 15.0; (-2.5555555555555554, 1.7777777777777777); 1; (345.0, 906.0); (342, 908); [None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 70; 9; 63; 15.0; (-2.5555555555555554, 1.7777777777777777); 2; (345.0, 906.0); (340, 910); [(391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 71; 10; 64; 15.0; (-2.5555555555555554, 1.6111111111111112); 1; (340.0, 909.0); (337, 911); [None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 72; 9; 65; 15.0; (-2.5555555555555554, 1.6111111111111112); 2; (340.0, 909.0); (335, 912); [(386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 73; 10; 66; 15.0; (-2.5555555555555554, 1.6666666666666667); 1; (336.0, 913.0); (333, 915); [None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 74; 9; 67; 15.0; (-2.5555555555555554, 1.6666666666666667); 2; (336.0, 913.0); (331, 916); [(382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 75; 10; 68; 15.0; (-2.5, 1.7222222222222223); 1; (330.0, 916.0); (328, 918); [None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0)];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 76; 9; 69; 15.0; (-2.5, 1.7222222222222223); 2; (330.0, 916.0); (325, 919); [(375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 77; 8; 70; 13.5; (-2.5, 1.6875); 3; (330.0, 916.0); (322, 921); [None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 78; 7; 71; 13.5; (-2.5, 1.6875); 4; (330.0, 916.0); (320, 923); [(370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]; 79; 6; 69; 12.0; (-2.5, 1.7142857142857142); 5; (330.0, 916.0); (318, 925); [None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]; 80; 5; 67; 12.0; (-2.5, 1.7142857142857142); 6; (330.0, 916.0); (315, 926); [(365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]; 81; 4; 65; 10.5; (-2.5, 1.6666666666666667); 7; (330.0, 916.0); (312, 928); [None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]; 82; 3; 63; 10.5; (-2.5, 1.6666666666666667); 8; (330.0, 916.0); (310, 929); [(360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]; 83; 2; 61; 9.0; (-2.5, 1.7); 9; (330.0, 916.0); (308, 931); [None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None, None];
-6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 84; 1; 59; 9.0; (-2.5, 1.7); 10; (330.0, 916.0); (305, 933); [(355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None, None, None];
-6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 85; 0; 57; 7.5; (-2.5, 1.75); 11; (330.0, 916.0); (302, 935); [None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None, None, None, None];
diff --git a/data/logs/satellite_log_2024-03-08_05-52-04.csv b/data/logs/satellite_log_2024-03-08_05-52-04.csv
new file mode 100644
index 0000000..716e87e
--- /dev/null
+++ b/data/logs/satellite_log_2024-03-08_05-52-04.csv
@@ -0,0 +1,195 @@
+id; last_times_detected; lifetime; left_lifetime; detection_confidence; blinking_freq; movement_vector; frames_since_last_detection; last_detected_position; next_expected_position; last_predicted_position last_positions;
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 28; 9; 21; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (993.0, 495.0); (988, 498); (993, 496); [(1036.0, 470.0), None, (1031.0, 472.0), None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 29; 10; 22; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (989.0, 498.0); (987, 499); (988, 498); [None, (1031.0, 472.0), None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 30; 9; 23; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (989.0, 498.0); (984, 501); (988, 498); [(1031.0, 472.0), None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 31; 10; 24; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (984, 501); (982, 502); (984, 501); [None, (1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 32; 9; 25; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (984, 501); (979, 504); (984, 501); [(1027.0, 476.0), None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 33; 10; 26; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (979, 504); (977, 505); (979, 504); [None, (1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 34; 9; 27; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (979, 504); (974, 507); (979, 504); [(1022, 479), None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 35; 10; 28; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (974.0, 506.0); (972, 507); (974, 507); [None, (1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 36; 9; 29; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (974.0, 506.0); (969, 509); (974, 507); [(1017.0, 481.0), None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 37; 10; 30; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (970.0, 510.0); (968, 511); (969, 509); [None, (1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1]; 38; 10; 31; 16.5; (-2.3333333333333335, 1.4444444444444444); 1; (970.0, 511.0); (968, 512); (968, 511); [(1012, 484), None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0)];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]; 39; 10; 32; 16.5; (-2.3125, 1.4375); 1; (964.0, 512.0); (962, 513); (968, 512); [None, (1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]; 40; 9; 33; 16.5; (-2.3125, 1.4375); 2; (964.0, 512.0); (959, 515); (968, 512); [(1007, 487), None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]; 41; 10; 34; 16.5; (-2.3125, 1.375); 1; (960.0, 514.0); (958, 515); (959, 515); [None, (1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1]; 42; 10; 32; 18.0; (-2.2941176470588234, 1.411764705882353); 1; (958.0, 516.0); (956, 517); (958, 515); [(1003.0, 490.0), None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0)];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1]; 43; 10; 30; 18.0; (-2.3125, 1.4375); 1; (955.0, 518.0); (953, 519); (956, 517); [None, (998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0]; 44; 9; 28; 18.0; (-2.3125, 1.4375); 2; (955.0, 518.0); (950, 521); (956, 517); [(998, 493), None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1]; 45; 10; 26; 18.0; (-2.3125, 1.5); 1; (950, 521); (948, 522); (950, 521); [None, (993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None, (950, 521)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0]; 46; 9; 24; 18.0; (-2.3125, 1.5); 2; (950, 521); (945, 524); (950, 521); [(993.0, 495.0), None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None, (950, 521), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 1]; 47; 10; 22; 18.0; (-2.375, 1.5); 1; (945, 524); (943, 526); (945, 524); [None, (989.0, 498.0), None, (984, 501), None, (979, 504), None, (974.0, 506.0), None, (970.0, 510.0), (970.0, 511.0), (964.0, 512.0), None, (960.0, 514.0), (958.0, 516.0), (955.0, 518.0), None, (950, 521), None, (945, 524)];
+5317; [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 136; 9; 21; 13.5; (-2.4375, 1.5); 2; (732, 655); (727, 658); (732, 655); [None, None, (771, 631), None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 137; 10; 22; 15.0; (-2.4444444444444446, 1.5); 1; (727, 658); (725, 660); (727, 658); [None, (771, 631), None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 138; 9; 23; 15.0; (-2.4444444444444446, 1.5); 2; (727, 658); (722, 661); (727, 658); [(771, 631), None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 139; 10; 24; 15.0; (-2.4444444444444446, 1.5); 1; (722, 661); (720, 662); (722, 661); [None, (766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 140; 9; 25; 15.0; (-2.4444444444444446, 1.5); 2; (722, 661); (717, 664); (722, 661); [(766, 634), None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 141; 10; 26; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (719.0, 663.0); (717, 664); (717, 664); [None, (761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 142; 9; 27; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (719.0, 663.0); (714, 666); (717, 664); [(761, 637), None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 143; 10; 28; 15.0; (-2.388888888888889, 1.4444444444444444); 1; (714, 666); (712, 667); (714, 666); [None, (757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 144; 9; 29; 15.0; (-2.388888888888889, 1.4444444444444444); 2; (714, 666); (709, 669); (714, 666); [(757.0, 640.0), None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 145; 10; 30; 15.0; (-2.388888888888889, 1.5555555555555556); 1; (709.0, 671.0); (707, 673); (709, 669); [None, (752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 146; 9; 31; 15.0; (-2.388888888888889, 1.5555555555555556); 2; (709.0, 671.0); (704, 674); (709, 669); [(752, 643), None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 147; 10; 32; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (703.0, 674.0); (701, 676); (704, 674); [None, (747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 148; 9; 33; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (703.0, 674.0); (698, 677); (704, 674); [(747, 646), None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 149; 10; 34; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (698, 677); (696, 679); (698, 677); [None, (742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1]; 150; 10; 35; 16.5; (-2.3684210526315788, 1.5263157894736843); 1; (697.0, 678.0); (695, 680); (696, 679); [(742, 649), None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0)];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]; 151; 10; 36; 16.5; (-2.4375, 1.5625); 1; (693.0, 680.0); (691, 682); (695, 680); [None, (737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]; 152; 9; 37; 16.5; (-2.4375, 1.5625); 2; (693.0, 680.0); (688, 683); (695, 680); [(737, 652), None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1]; 153; 10; 38; 16.5; (-2.4375, 1.5625); 1; (688, 683); (686, 685); (688, 683); [None, (732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0]; 154; 9; 39; 16.5; (-2.4375, 1.5625); 2; (688, 683); (683, 686); (688, 683); [(732, 655), None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1]; 155; 10; 40; 16.5; (-2.2941176470588234, 1.5294117647058822); 1; (684.0, 686.0); (682, 688); (683, 686); [None, (727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0]; 156; 9; 41; 16.5; (-2.2941176470588234, 1.5294117647058822); 2; (684.0, 686.0); (679, 689); (683, 686); [(727, 658), None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1]; 157; 10; 42; 16.5; (-2.2941176470588234, 1.5294117647058822); 1; (679, 689); (677, 691); (679, 689); [None, (722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0]; 158; 9; 43; 16.5; (-2.2941176470588234, 1.5294117647058822); 2; (679, 689); (674, 692); (679, 689); [(722, 661), None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 159; 10; 44; 16.5; (-2.6470588235294117, 1.6470588235294117); 1; (673.0, 692.0); (670, 694); (674, 692); [None, (719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 160; 9; 45; 16.5; (-2.6470588235294117, 1.6470588235294117); 2; (673.0, 692.0); (668, 695); (674, 692); [(719.0, 663.0), None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 161; 10; 46; 16.5; (-2.5, 1.625); 1; (669.0, 695.0); (666, 697); (668, 695); [None, (714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 162; 9; 47; 16.5; (-2.5, 1.625); 2; (669.0, 695.0); (664, 698); (668, 695); [(714, 666), None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None];
+5317; [0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 163; 10; 48; 16.5; (-2.5, 1.5); 1; (664, 698); (662, 700); (664, 698); [None, (709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698)];
+5317; [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 164; 9; 49; 16.5; (-2.5, 1.5); 2; (664, 698); (659, 701); (664, 698); [(709.0, 671.0), None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None];
+5317; [0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 165; 10; 50; 16.5; (-2.4375, 1.5625); 1; (659.0, 702.0); (657, 704); (659, 701); [None, (703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0)];
+5317; [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 166; 9; 51; 16.5; (-2.4375, 1.5625); 2; (659.0, 702.0); (654, 705); (659, 701); [(703.0, 674.0), None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None];
+5317; [0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 167; 10; 52; 16.5; (-2.4375, 1.5625); 1; (654, 705); (652, 707); (654, 705); [None, (698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705)];
+5317; [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 168; 9; 53; 16.5; (-2.4375, 1.5625); 2; (654, 705); (649, 708); (654, 705); [(698, 677), (697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None];
+5317; [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 169; 10; 54; 16.5; (-2.4444444444444446, 1.5555555555555556); 1; (649, 708); (647, 710); (649, 708); [(697.0, 678.0), (693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 170; 9; 55; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (649, 708); (644, 711); (649, 708); [(693.0, 680.0), None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 171; 10; 56; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (644, 711); (642, 713); (644, 711); [None, (688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 172; 9; 57; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (644, 711); (639, 714); (644, 711); [(688, 683), None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 173; 10; 58; 15.0; (-2.5, 1.5555555555555556); 1; (639, 714); (636, 716); (639, 714); [None, (684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 174; 9; 59; 15.0; (-2.5, 1.5555555555555556); 2; (639, 714); (634, 717); (639, 714); [(684.0, 686.0), None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 175; 10; 60; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (635.0, 718.0); (633, 720); (634, 717); [None, (679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 176; 9; 61; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (635.0, 718.0); (630, 721); (634, 717); [(679, 689), None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 177; 10; 62; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (629.0, 720.0); (627, 722); (630, 721); [None, (673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 178; 9; 63; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (629.0, 720.0); (624, 723); (630, 721); [(673.0, 692.0), None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 179; 10; 64; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (625.0, 724.0); (623, 726); (624, 723); [None, (669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 180; 9; 65; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (625.0, 724.0); (620, 727); (624, 723); [(669.0, 695.0), None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 181; 10; 66; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (620, 727); (618, 729); (620, 727); [None, (664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 182; 9; 67; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (620, 727); (615, 730); (620, 727); [(664, 698), None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 183; 10; 68; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (615, 730); (613, 732); (615, 730); [None, (659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 184; 9; 69; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (615, 730); (610, 733); (615, 730); [(659.0, 702.0), None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 185; 10; 70; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (610, 733); (608, 735); (610, 733); [None, (654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 186; 9; 71; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (610, 733); (605, 736); (610, 733); [(654, 705), None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 187; 10; 72; 15.0; (-2.3333333333333335, 1.5); 1; (607.0, 735.0); (605, 736); (605, 736); [None, (649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 188; 9; 73; 15.0; (-2.3333333333333335, 1.5); 2; (607.0, 735.0); (602, 738); (605, 736); [(649, 708), None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 189; 10; 74; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (602.0, 737.0); (600, 738); (602, 738); [None, (644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 190; 9; 75; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (602.0, 737.0); (597, 740); (602, 738); [(644, 711), None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 191; 10; 76; 15.0; (-2.2777777777777777, 1.5); 1; (598.0, 741.0); (596, 742); (597, 740); [None, (639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 192; 9; 77; 15.0; (-2.2777777777777777, 1.5); 2; (598.0, 741.0); (593, 744); (597, 740); [(639, 714), None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 193; 10; 78; 15.0; (-2.388888888888889, 1.3888888888888888); 1; (592.0, 743.0); (590, 744); (593, 744); [None, (635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 194; 9; 79; 15.0; (-2.388888888888889, 1.3888888888888888); 2; (592.0, 743.0); (587, 746); (593, 744); [(635.0, 718.0), None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 195; 10; 80; 15.0; (-2.2777777777777777, 1.5); 1; (588.0, 747.0); (586, 748); (587, 746); [None, (629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 196; 9; 81; 15.0; (-2.2777777777777777, 1.5); 2; (588.0, 747.0); (583, 750); (587, 746); [(629.0, 720.0), None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 197; 10; 82; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (583, 750); (581, 751); (583, 750); [None, (625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 198; 9; 83; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (583, 750); (578, 753); (583, 750); [(625.0, 724.0), None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 199; 10; 84; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (578, 753); (576, 754); (578, 753); [None, (620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 200; 9; 85; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (578, 753); (573, 756); (578, 753); [(620, 727), None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 201; 10; 86; 15.0; (-2.3333333333333335, 1.4444444444444444); 1; (573, 756); (571, 757); (573, 756); [None, (615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 202; 9; 87; 15.0; (-2.3333333333333335, 1.4444444444444444); 2; (573, 756); (568, 759); (573, 756); [(615, 730), None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 203; 10; 88; 15.0; (-2.3333333333333335, 1.5); 1; (568.0, 760.0); (566, 762); (568, 759); [None, (610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 204; 9; 89; 15.0; (-2.3333333333333335, 1.5); 2; (568.0, 760.0); (563, 763); (568, 759); [(610, 733), None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 205; 10; 90; 15.0; (-2.4444444444444446, 1.5555555555555556); 1; (563, 763); (561, 765); (563, 763); [None, (607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 206; 9; 91; 15.0; (-2.4444444444444446, 1.5555555555555556); 2; (563, 763); (558, 766); (563, 763); [(607.0, 735.0), None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 207; 10; 92; 15.0; (-2.388888888888889, 1.6111111111111112); 1; (559.0, 766.0); (557, 768); (558, 766); [None, (602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 208; 9; 93; 15.0; (-2.388888888888889, 1.6111111111111112); 2; (559.0, 766.0); (554, 769); (558, 766); [(602.0, 737.0), None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 209; 10; 94; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (554.0, 770.0); (552, 772); (554, 769); [None, (598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 210; 9; 95; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (554.0, 770.0); (549, 773); (554, 769); [(598.0, 741.0), None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 211; 10; 96; 15.0; (-2.4444444444444446, 1.6111111111111112); 1; (548.0, 772.0); (546, 774); (549, 773); [None, (592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 212; 9; 97; 15.0; (-2.4444444444444446, 1.6111111111111112); 2; (548.0, 772.0); (543, 775); (549, 773); [(592.0, 743.0), None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 213; 10; 98; 15.0; (-2.5, 1.5555555555555556); 1; (543, 775); (540, 777); (543, 775); [None, (588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1]; 214; 10; 99; 16.5; (-2.5, 1.5555555555555556); 1; (543.0, 774.0); (540, 776); (540, 777); [(588.0, 747.0), None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0)];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1]; 215; 10; 100; 16.5; (-2.5, 1.5625); 1; (533.0, 778.0); (530, 780); (540, 776); [None, (583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0]; 216; 9; 101; 16.5; (-2.5, 1.5625); 2; (533.0, 778.0); (528, 781); (540, 776); [(583, 750), None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0]; 217; 8; 102; 15.0; (-2.5, 1.5714285714285714); 3; (533.0, 778.0); (526, 783); (540, 776); [None, (578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0]; 218; 7; 103; 15.0; (-2.5, 1.5714285714285714); 4; (533.0, 778.0); (523, 784); (540, 776); [(578, 753), None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1]; 219; 10; 104; 15.0; (-2.125, 1.625); 1; (529.0, 785.0); (527, 787); (523, 784); [None, (573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1]; 220; 10; 105; 16.5; (-2.0588235294117645, 1.588235294117647); 1; (528.0, 786.0); (526, 788); (527, 787); [(573, 756), None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0)];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1]; 221; 10; 106; 16.5; (-2.0, 1.5333333333333334); 1; (525.0, 786.0); (523, 788); (526, 788); [None, (568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0]; 222; 9; 107; 16.5; (-2.0, 1.5333333333333334); 2; (525.0, 786.0); (521, 789); (526, 788); [(568.0, 760.0), None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1]; 223; 10; 108; 16.5; (-2.142857142857143, 1.7857142857142858); 1; (519.0, 792.0); (517, 794); (521, 789); [None, (563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0]; 224; 9; 109; 16.5; (-2.142857142857143, 1.7857142857142858); 2; (519.0, 792.0); (515, 796); (521, 789); [(563, 763), None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1]; 225; 10; 110; 16.5; (-2.7, 1.8); 1; (514.0, 795.0); (511, 797); (515, 796); [None, (559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0]; 226; 9; 111; 16.5; (-2.7, 1.8); 2; (514.0, 795.0); (509, 799); (515, 796); [(559.0, 766.0), None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None];
+5317; [0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1]; 227; 10; 112; 16.5; (-2.625, 1.375); 1; (509.0, 798.0); (506, 799); (509, 799); [None, (554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0)];
+5317; [1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0]; 228; 9; 113; 16.5; (-2.625, 1.375); 2; (509.0, 798.0); (504, 801); (509, 799); [(554.0, 770.0), None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None];
+5317; [0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 229; 8; 114; 15.0; (-2.0833333333333335, 1.8333333333333333); 3; (509.0, 798.0); (503, 804); (509, 799); [None, (548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None];
+5317; [1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 230; 7; 115; 15.0; (-2.0833333333333335, 1.8333333333333333); 4; (509.0, 798.0); (501, 805); (509, 799); [(548.0, 772.0), None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None];
+5317; [0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]; 231; 6; 116; 13.5; (-2.0, 1.9); 5; (509.0, 798.0); (499, 808); (509, 799); [None, (543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None];
+5317; [1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]; 232; 5; 117; 13.5; (-2.0, 1.9); 6; (509.0, 798.0); (497, 809); (509, 799); [(543, 775), (543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None];
+5317; [1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]; 233; 10; 118; 13.5; (-2.5833333333333335, 1.8333333333333337); 1; (494.0, 808.0); (491, 810); (497, 809); [(543.0, 774.0), (533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0)];
+5317; [1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0]; 234; 9; 116; 12.0; (-2.0, 1.6000000000000003); 2; (494.0, 808.0); (490, 811); (497, 809); [(533.0, 778.0), None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None];
+5317; [0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]; 235; 10; 114; 12.0; (-2.4166666666666665, 1.4166666666666667); 1; (490.0, 809.0); (488, 810); (490, 811); [None, None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0)];
+5317; [0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0]; 236; 9; 112; 12.0; (-2.4166666666666665, 1.4166666666666667); 2; (490.0, 809.0); (485, 812); (490, 811); [None, None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None];
+5317; [0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0]; 237; 8; 110; 12.0; (-2.4166666666666665, 1.4166666666666667); 3; (490.0, 809.0); (483, 813); (490, 811); [None, (529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None];
+5317; [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0]; 238; 7; 108; 12.0; (-2.4166666666666665, 1.4166666666666667); 4; (490.0, 809.0); (480, 815); (490, 811); [(529.0, 785.0), (528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None];
+5317; [1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0]; 239; 6; 106; 10.5; (-2.4166666666666665, 1.4166666666666667); 5; (490.0, 809.0); (478, 816); (490, 811); [(528.0, 786.0), (525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0]; 240; 5; 104; 9.0; (-2.5, 1.642857142857143); 6; (490.0, 809.0); (475, 819); (490, 811); [(525.0, 786.0), None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None];
+5317; [0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1]; 241; 10; 102; 9.0; (-2.3888888888888893, 1.5000000000000004); 1; (476.0, 819.0); (474, 820); (475, 819); [None, (519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0)];
+5317; [1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0]; 242; 9; 100; 9.0; (-2.3888888888888893, 1.5000000000000004); 2; (476.0, 819.0); (471, 822); (475, 819); [(519.0, 792.0), None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None];
+5317; [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1]; 243; 10; 98; 9.0; (-2.388888888888889, 1.5000000000000002); 1; (471, 822); (469, 824); (471, 822); [None, (514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822)];
+5317; [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0]; 244; 9; 96; 9.0; (-2.388888888888889, 1.5000000000000002); 2; (471, 822); (466, 825); (471, 822); [(514.0, 795.0), None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None];
+5317; [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1]; 245; 10; 94; 9.0; (-2.4999999999999996, 1.6111111111111112); 1; (464.0, 827.0); (462, 829); (466, 825); [None, (509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0)];
+5317; [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0]; 246; 9; 92; 9.0; (-2.4999999999999996, 1.6111111111111112); 2; (464.0, 827.0); (459, 830); (466, 825); [(509.0, 798.0), None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None];
+5317; [0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]; 247; 10; 90; 9.0; (-2.4285714285714284, 1.6428571428571428); 1; (460.0, 831.0); (458, 833); (459, 830); [None, None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0)];
+5317; [0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 248; 9; 88; 9.0; (-2.4285714285714284, 1.6428571428571428); 2; (460.0, 831.0); (455, 834); (459, 830); [None, None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None];
+5317; [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 249; 10; 86; 10.5; (-2.4375, 1.625); 1; (455, 834); (453, 836); (455, 834); [None, None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834)];
+5317; [0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 250; 9; 84; 10.5; (-2.4375, 1.625); 2; (455, 834); (450, 837); (455, 834); [None, None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None];
+5317; [0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 251; 8; 82; 10.5; (-2.4375, 1.625); 3; (455, 834); (448, 839); (455, 834); [None, (494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None];
+5317; [1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 252; 7; 80; 10.5; (-2.4375, 1.625); 4; (455, 834); (445, 840); (455, 834); [(494.0, 808.0), None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None];
+5317; [0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1]; 253; 10; 78; 10.5; (-2.388888888888889, 1.7222222222222223); 1; (447.0, 840.0); (445, 842); (445, 840); [None, (490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0)];
+5317; [1, 0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0]; 254; 9; 76; 10.5; (-2.388888888888889, 1.7222222222222223); 2; (447.0, 840.0); (442, 843); (445, 840); [(490.0, 809.0), None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None];
+5317; [0, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]; 255; 10; 74; 10.5; (-2.5714285714285716, 1.5714285714285714); 1; (440.0, 841.0); (437, 843); (442, 843); [None, None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0)];
+5317; [0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]; 256; 9; 72; 10.5; (-2.5714285714285716, 1.5714285714285714); 2; (440.0, 841.0); (435, 844); (442, 843); [None, None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None];
+5317; [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1]; 257; 10; 70; 12.0; (-2.5625, 1.5625); 1; (435, 844); (432, 846); (435, 844); [None, None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844)];
+5317; [0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0]; 258; 9; 68; 12.0; (-2.5625, 1.5625); 2; (435, 844); (430, 847); (435, 844); [None, None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0]; 259; 8; 66; 12.0; (-2.5625, 1.5625); 3; (435, 844); (427, 849); (435, 844); [None, (476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 260; 7; 64; 12.0; (-2.5625, 1.5625); 4; (435, 844); (425, 850); (435, 844); [(476.0, 819.0), None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None];
+5317; [0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1]; 261; 10; 62; 12.0; (-2.5, 1.6111111111111112); 1; (426.0, 851.0); (424, 853); (425, 850); [None, (471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0)];
+5317; [1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0]; 262; 9; 60; 12.0; (-2.5, 1.6111111111111112); 2; (426.0, 851.0); (421, 854); (425, 850); [(471, 822), None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1]; 263; 10; 58; 12.0; (-2.388888888888889, 1.5); 1; (421, 854); (419, 856); (421, 854); [None, (464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854)];
+5317; [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0]; 264; 9; 56; 12.0; (-2.388888888888889, 1.5); 2; (421, 854); (416, 857); (421, 854); [(464.0, 827.0), None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None];
+5317; [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1]; 265; 10; 54; 12.0; (-2.4444444444444446, 1.4444444444444444); 1; (416, 857); (414, 858); (416, 857); [None, (460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857)];
+5317; [1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0]; 266; 9; 52; 12.0; (-2.4444444444444446, 1.4444444444444444); 2; (416, 857); (411, 860); (416, 857); [(460.0, 831.0), None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None];
+5317; [0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1]; 267; 10; 50; 12.0; (-2.4444444444444446, 1.5); 1; (411.0, 861.0); (409, 862); (411, 860); [None, (455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0)];
+5317; [1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 268; 9; 48; 12.0; (-2.4444444444444446, 1.5); 2; (411.0, 861.0); (406, 864); (411, 860); [(455, 834), None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None];
+5317; [0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 269; 10; 46; 12.0; (-2.5625, 1.5); 1; (406, 864); (403, 866); (406, 864); [None, None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864)];
+5317; [0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 270; 9; 44; 12.0; (-2.5625, 1.5); 2; (406, 864); (401, 867); (406, 864); [None, None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None];
+5317; [0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 271; 10; 45; 13.5; (-2.5555555555555554, 1.5); 1; (401, 867); (398, 868); (401, 867); [None, (447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None, (401, 867)];
+5317; [1, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 272; 9; 46; 13.5; (-2.5555555555555554, 1.5); 2; (401, 867); (396, 870); (401, 867); [(447.0, 840.0), None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None, (401, 867), None];
+5317; [0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 273; 8; 44; 12.0; (-2.4375, 1.625); 3; (401, 867); (394, 872); (401, 867); [None, (440.0, 841.0), None, (435, 844), None, None, None, (426.0, 851.0), None, (421, 854), None, (416, 857), None, (411.0, 861.0), None, (406, 864), None, (401, 867), None, None];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0]; 50; 9; 43; 16.5; (-2.5, 1.6111111111111112); 2; (395, 872); (390, 875); (395, 872); [(440.0, 843.0), None, (435.0, 847.0), None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 51; 10; 44; 16.5; (-2.4444444444444446, 1.5); 1; (391.0, 874.0); (389, 876); (390, 875); [None, (435.0, 847.0), None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 52; 9; 45; 16.5; (-2.4444444444444446, 1.5); 2; (391.0, 874.0); (386, 877); (390, 875); [(435.0, 847.0), None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 53; 10; 46; 16.5; (-2.4444444444444446, 1.6666666666666667); 1; (386.0, 880.0); (384, 882); (386, 877); [None, (430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 54; 9; 47; 16.5; (-2.4444444444444446, 1.6666666666666667); 2; (386.0, 880.0); (381, 883); (386, 877); [(430.0, 850.0), None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None];
+6204; [0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 55; 10; 48; 16.5; (-2.388888888888889, 1.6666666666666667); 1; (382.0, 883.0); (380, 885); (381, 883); [None, (425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0)];
+6204; [1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 56; 9; 49; 16.5; (-2.388888888888889, 1.6666666666666667); 2; (382.0, 883.0); (377, 886); (381, 883); [(425, 853), None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None];
+6204; [0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 57; 10; 50; 16.5; (-2.5, 1.6111111111111112); 1; (375.0, 885.0); (372, 887); (377, 886); [None, (420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0)];
+6204; [1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 58; 9; 51; 16.5; (-2.5, 1.6111111111111112); 2; (375.0, 885.0); (370, 888); (377, 886); [(420, 856), None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None];
+6204; [0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 59; 10; 52; 16.5; (-2.5, 1.6666666666666667); 1; (370.0, 889.0); (368, 891); (370, 888); [None, (415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0)];
+6204; [1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 60; 9; 53; 16.5; (-2.5, 1.6666666666666667); 2; (370.0, 889.0); (365, 892); (370, 888); [(415, 859), (412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None];
+6204; [1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 61; 10; 54; 16.5; (-2.473684210526316, 1.631578947368421); 1; (365, 892); (363, 894); (365, 892); [(412, 861), (410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 62; 9; 55; 15.0; (-2.5, 1.6111111111111112); 2; (365, 892); (360, 895); (365, 892); [(410.0, 863.0), None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 63; 10; 56; 15.0; (-2.5, 1.6666666666666667); 1; (360.0, 896.0); (358, 898); (360, 895); [None, (405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 64; 9; 57; 15.0; (-2.5, 1.6666666666666667); 2; (360.0, 896.0); (355, 899); (360, 895); [(405.0, 866.0), None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 65; 10; 58; 15.0; (-2.5, 1.6666666666666667); 1; (355, 899); (352, 901); (355, 899); [None, (400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 66; 9; 59; 15.0; (-2.5, 1.6666666666666667); 2; (355, 899); (350, 902); (355, 899); [(400, 869), None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 67; 10; 60; 15.0; (-2.5, 1.6666666666666667); 1; (350, 902); (348, 904); (350, 902); [None, (395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 68; 9; 61; 15.0; (-2.5, 1.6666666666666667); 2; (350, 902); (345, 905); (350, 902); [(395, 872), None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 69; 10; 62; 15.0; (-2.5555555555555554, 1.7777777777777777); 1; (345.0, 906.0); (342, 908); (345, 905); [None, (391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 70; 9; 63; 15.0; (-2.5555555555555554, 1.7777777777777777); 2; (345.0, 906.0); (340, 910); (345, 905); [(391.0, 874.0), None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 71; 10; 64; 15.0; (-2.5555555555555554, 1.6111111111111112); 1; (340.0, 909.0); (337, 911); (340, 910); [None, (386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 72; 9; 65; 15.0; (-2.5555555555555554, 1.6111111111111112); 2; (340.0, 909.0); (335, 912); (340, 910); [(386.0, 880.0), None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 73; 10; 66; 15.0; (-2.5555555555555554, 1.6666666666666667); 1; (336.0, 913.0); (333, 915); (335, 912); [None, (382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 74; 9; 67; 15.0; (-2.5555555555555554, 1.6666666666666667); 2; (336.0, 913.0); (331, 916); (335, 912); [(382.0, 883.0), None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1]; 75; 10; 68; 15.0; (-2.5, 1.7222222222222223); 1; (330.0, 916.0); (328, 918); (331, 916); [None, (375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0)];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0]; 76; 9; 69; 15.0; (-2.5, 1.7222222222222223); 2; (330.0, 916.0); (325, 919); (331, 916); [(375.0, 885.0), None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0]; 77; 8; 70; 13.5; (-2.5, 1.6875); 3; (330.0, 916.0); (322, 921); (331, 916); [None, (370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0]; 78; 7; 71; 13.5; (-2.5, 1.6875); 4; (330.0, 916.0); (320, 923); (331, 916); [(370.0, 889.0), None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0]; 79; 6; 69; 12.0; (-2.5, 1.7142857142857142); 5; (330.0, 916.0); (318, 925); (331, 916); [None, (365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0]; 80; 5; 67; 12.0; (-2.5, 1.7142857142857142); 6; (330.0, 916.0); (315, 926); (331, 916); [(365, 892), None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0]; 81; 4; 65; 10.5; (-2.5, 1.6666666666666667); 7; (330.0, 916.0); (312, 928); (331, 916); [None, (360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0]; 82; 3; 63; 10.5; (-2.5, 1.6666666666666667); 8; (330.0, 916.0); (310, 929); (331, 916); [(360.0, 896.0), None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0]; 83; 2; 61; 9.0; (-2.5, 1.7); 9; (330.0, 916.0); (308, 931); (331, 916); [None, (355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None, None];
+6204; [1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 84; 1; 59; 9.0; (-2.5, 1.7); 10; (330.0, 916.0); (305, 933); (331, 916); [(355, 899), None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None, None, None];
+6204; [0, 1, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]; 85; 0; 57; 7.5; (-2.5, 1.75); 11; (330.0, 916.0); (302, 935); (331, 916); [None, (350, 902), None, (345.0, 906.0), None, (340.0, 909.0), None, (336.0, 913.0), None, (330.0, 916.0), None, None, None, None, None, None, None, None, None, None];
diff --git a/data/videos/README.md b/data/videos/README.md
index 530e42c..587a5ab 100644
--- a/data/videos/README.md
+++ b/data/videos/README.md
@@ -2,10 +2,10 @@ In this folder can be found some videos used to test the implemented algorithms.
A detailed explanation of each video is shown below.
-* video1: "simple" test-video from internet in it's original state (video stored at 30 fps).
+* video1: "simple" test-video from internet in its original state (video stored at 30 fps).
* video2: a copy from video1 where the brightest star has been "removed" from half of the frames to simulate the satellite blinking at a frequency of 15 Hz (video stored at 30 fps).
-* video3: a more "complex" test-video from internet in it's original state (video stored at 30 fps).
-* video4: a copy from video3 where a satellite that crosses the sky (from 00:30 to 00:40 aprox) has been "removed" from half of the frames to simulate the satellite blinking at a frequency of 15 Hz (video stored at 30 fps).
-* video5: a copy from video3 where a satellite that crosses the sky (from 00:30 to 00:40 aprox) has been "removed" from two thirds of the frames to simulate the satellite blinking at a frequency of 10 Hz (video stored at 30 fps).
+* video3: a more "complex" test-video from internet in its original state (video stored at 30 fps).
+* video4: a copy from video3 where a satellite that crosses the sky (from 00:30 to 00:40 approx) has been "removed" from half of the frames to simulate the satellite blinking at a frequency of 15 Hz (video stored at 30 fps).
+* video5: a copy from video3 where a satellite that crosses the sky (from 00:30 to 00:40 approx) has been "removed" from two thirds of the frames to simulate the satellite blinking at a frequency of 10 Hz (video stored at 30 fps).
* video6: a copy from video5 downscaled to 480p to lose information to make some tests.
-* video7: a copy from video6 upscaled to 1080p again to maintain the number of pixels but with the information of the 480p version to make some tests.
+* video7: a copy from video6 up-scaled to 1080p again to maintain the number of pixels but with the information of the 480p version to make some tests.
diff --git a/docker-compose.yml b/docker-compose.yml
new file mode 100644
index 0000000..e6e53da
--- /dev/null
+++ b/docker-compose.yml
@@ -0,0 +1,30 @@
+services:
+ teidesat-cubesat-tracker:
+ image: teidesat-cubesat-tracker:latest
+ build:
+ context: .
+ dockerfile: Dockerfile
+ container_name: teidesat-cubesat-tracker
+ network_mode: host
+ runtime: nvidia
+ env_file:
+ - .env
+ environment:
+ - DISPLAY=${DISPLAY}
+ volumes:
+ - /dev/bus/usb:/dev/bus/usb:ro
+ - /tmp/.X11-unix:/tmp/.X11-unix:ro
+ - $HOME/.Xauthority:/root/.Xauthority:ro
+ - .:/app
+ - ${TRAINED_MODELS_PATH}:/app/trained-models
+ device_cgroup_rules:
+ - c 189:* rmw
+ deploy:
+ resources:
+ reservations:
+ devices:
+ - driver: nvidia
+ count: 1
+ capabilities: [gpu]
+ working_dir: /app
+ command: "python3 main.py"
diff --git a/extra utilities/cameras_detector.py b/extra utilities/cameras_detector.py
index 7f830f8..e3324f8 100755
--- a/extra utilities/cameras_detector.py
+++ b/extra utilities/cameras_detector.py
@@ -10,18 +10,24 @@
def main():
available_ports, working_ports = detect_cameras()
+ print("Ignore index warnings/errors if any.", end="\n\n")
+ print("Found cameras:")
+
for working_port, width, height, fps in working_ports:
print(
- f"Port {working_port} is working and reads images "
+ f" * Port {working_port} is working and reads images "
+ f"({width}x{height} - {fps} fps)"
)
for available_port, width, height, fps in available_ports:
print(
- f"Port {available_port} for camera ({width}x{height} - {fps} fps) "
+ f" * Port {available_port} for camera ({width}x{height} - {fps} fps) "
+ "is present but does not reads."
)
+ if not available_ports and not working_ports:
+ print(" * No cameras found.")
+
def detect_cameras():
"""Function to detect all available cameras."""
diff --git a/main.py b/main.py
index 271acf9..19b9c5d 100755
--- a/main.py
+++ b/main.py
@@ -10,170 +10,224 @@
# This program is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE. See the GNU General Public License for more details. You should
-# have received a copy of the GNU General Public License along with this program. If
+# have received a copy of the GNU General Public License along with this program. If
# not, see .
""" # ToDo: complete module docstring
# ToDo: add the missing module information
__authors__ = ["Jorge Sierra", "Sergio Tabares Hernández"]
-# __contact__ = "mail@example.com"
+__contact__ = "teidesat@ull.edu.es"
# __copyright__ = "Copyright $YEAR, $COMPANY_NAME"
__credits__ = ["Jorge Sierra", "Sergio Tabares Hernández"]
-__date__ = "2022/06/12"
+__date__ = "2024/10/25"
__deprecated__ = False
-# __email__ = "mail@example.com"
+__email__ = "teidesat@ull.edu.es"
# __license__ = "GPLv3"
__maintainer__ = "Sergio Tabares Hernández"
__status__ = "Production"
-__version__ = "0.0.9"
+__version__ = "0.0.10"
from copy import deepcopy
-from itertools import pairwise
-import sys
-from time import perf_counter
+from sys import exit as sys__exit
+from time import perf_counter as time__perf_counter
import cv2 as cv
from src.image_processor import (
+ load_star_detector,
detect_stars,
track_stars,
detect_blinking_star,
detect_shooting_stars,
)
+from src.input_stream import InputStream
from src.star import Star
+
from constants import (
+ SHOW_VIDEO_RESULT,
+ SIMULATE_TRACKING,
+ OUTPUT_RAW_VIDEO_TO_FILE,
+ PATH_OUTPUT_RAW_VIDEO,
+ OUTPUT_PROCESSED_VIDEO_TO_FILE,
+ PATH_OUTPUT_PROCESSED_VIDEO,
+ OUTPUT_SAT_LOG_TO_FILE,
+ PATH_OUTPUT_SAT_LOG,
+ STAR_DETECTION_MODE,
STAR_DETECTOR_THRESHOLD,
- FAST,
+ NEURAL_NETWORK_MODEL_PATH,
+ PRUNE_CLOSE_POINTS,
MIN_PRUNE_DISTANCE,
SAT_DESIRED_BLINKING_FREQ,
MOVEMENT_THRESHOLD,
- PX_SENSITIVITY,
- PATH_VIDEO,
- PATH_SAT_LOG,
- RGB_IMAGE,
- VIDEO_FROM_CAMERA,
- SHOW_VIDEO_RESULT,
- COLORIZED_TRACKED_STARS,
- OUTPUT_VIDEO_TO_FILE,
- PATH_OUTPUT_VIDEO,
)
def main():
"""Main function to start the program execution."""
- if VIDEO_FROM_CAMERA:
- video_path = 0 # Default webcam id
- print("Processing video from camera number ", video_path)
-
- else:
- video_path = str(PATH_VIDEO)
- print("Processing video from:", video_path)
-
- vid_cap = cv.VideoCapture(video_path)
- if not vid_cap.isOpened():
- sys.exit("\nError: Unable to open video.")
-
- satellite_detection_test(vid_cap)
+ satellite_detection_test()
def satellite_detection_test(
- vid_cap,
sat_desired_blinking_freq: float = SAT_DESIRED_BLINKING_FREQ,
+ star_detection_mode: str = STAR_DETECTION_MODE,
star_detector_threshold: int = STAR_DETECTOR_THRESHOLD,
- fast: bool = FAST,
+ neural_network_model_path: str = str(NEURAL_NETWORK_MODEL_PATH),
+ prune_close_points: bool = PRUNE_CLOSE_POINTS,
min_prune_distance: float = MIN_PRUNE_DISTANCE,
movement_threshold: float = MOVEMENT_THRESHOLD,
- rgb_image: bool = RGB_IMAGE,
show_video_result: bool = SHOW_VIDEO_RESULT,
- output_video_to_file: bool = OUTPUT_VIDEO_TO_FILE,
+ simulate_tracking: bool = SIMULATE_TRACKING,
+ output_sat_log_to_file: bool = OUTPUT_SAT_LOG_TO_FILE,
+ path_output_sat_log: str = str(PATH_OUTPUT_SAT_LOG),
+ output_raw_video_to_file: bool = OUTPUT_RAW_VIDEO_TO_FILE,
+ path_output_raw_video: str = str(PATH_OUTPUT_RAW_VIDEO),
+ output_processed_video_to_file: bool = OUTPUT_PROCESSED_VIDEO_TO_FILE,
+ path_output_processed_video: str = str(PATH_OUTPUT_PROCESSED_VIDEO),
):
"""Function to detect and track the satellite."""
- # if VIDEO_FROM_CAMERA this could not work
- video_fps = vid_cap.get(cv.CAP_PROP_FPS)
+ # Create input stream object to initialize the source of video frames
+ input_stream = InputStream()
- star_detector = cv.FastFeatureDetector_create(threshold=star_detector_threshold)
+ # Create the star detector object
+ star_detector = load_star_detector(
+ star_detection_mode,
+ star_detector_threshold,
+ neural_network_model_path,
+ )
+ # Initialize the variables to store the information about the tracked stars and the
+ # detected satellite through the video frames
tracked_stars: set[Star] = set()
satellite_log: list[Star] = []
- wait_time = 1
- wait_options = {
+ # Initialize the visualization variables
+ wait_time = 1 # Default visualization speed
+ wait_options = { # Visualization speed options
ord("z"): 1,
ord("x"): 100,
ord("c"): 1000,
ord("v"): 0,
}
+ # Initialize the statistics variables
processed_frames = 0
- start_time = perf_counter()
+ start_time = time__perf_counter()
- output_video = create_export_video_file(vid_cap) if output_video_to_file else None
+ # Initialize the output video files if needed
+ output_raw_video = (
+ create_export_video_file(input_stream, path_output_raw_video)
+ if output_raw_video_to_file
+ else None
+ )
+ output_processed_video = (
+ create_export_video_file(input_stream, path_output_processed_video)
+ if output_processed_video_to_file
+ else None
+ )
+ # Initialize the visualization window if needed
if show_video_result:
cv.namedWindow("Satellite detection", cv.WINDOW_NORMAL)
+ # Start the main processing loop
while True:
- success, frame = vid_cap.read()
- if not success:
- break
+
+ # Get the next frame from the input stream
+ raw_frame = input_stream.get_next_frame()
+ if raw_frame is None:
+ if input_stream.source_type == "VIDEO_FILE":
+ break # Exiting because the video file has probably ended
+ else:
+ continue
processed_frames += 1
- gray = cv.cvtColor(frame, cv.COLOR_RGB2GRAY) if rgb_image else frame
+ # Convert the frame to grayscale if not already
+ grayscale_frame = raw_frame.to_grayscale()
- new_star_positions = detect_stars(gray, star_detector, fast, min_prune_distance)
+ # Detect the sky objects in the current frame
+ new_star_positions = detect_stars(
+ grayscale_frame,
+ star_detector,
+ star_detection_mode,
+ prune_close_points,
+ min_prune_distance,
+ )
+ # Update the tracked sky objects information with the new detected positions
track_stars(
new_star_positions,
tracked_stars,
sat_desired_blinking_freq,
- video_fps,
+ input_stream.fps,
)
+ # Filter the fast moving objects
shooting_stars = detect_shooting_stars(tracked_stars, movement_threshold)
+ # Get the object with the blinking frequency closest to the desired one
satellite = detect_blinking_star(shooting_stars)
- show_frame = (
- frame.copy() if rgb_image else cv.cvtColor(frame, cv.COLOR_GRAY2RGB)
- )
-
- # draw_found_stars(show_frame, new_star_positions)
-
- draw_tracked_stars(show_frame, tracked_stars)
+ # Prepare a copy of the raw frame to mark the detected objects
+ show_frame = raw_frame.to_colorspace()
- draw_path(show_frame, shooting_stars)
- draw_shooting_stars(show_frame, shooting_stars)
- draw_expected_position(show_frame, shooting_stars)
+ # Mark the detected objects in the frame
+ show_frame.mark(
+ new_star_positions,
+ tracked_stars,
+ shooting_stars,
+ satellite,
+ )
if satellite is not None:
+ # Save the current satellite information to store as a log
satellite_log.append(deepcopy(satellite))
- draw_path(show_frame, satellite)
- draw_satellite(show_frame, satellite)
- draw_expected_position(show_frame, satellite)
+ # Transform the frame to simulate the tracking phase if needed
+ if simulate_tracking:
+ show_frame.tracking_phase_video_simulation(satellite)
+
+ # Export the raw frame to the output video file if needed
+ if output_raw_video is not None:
+ output_raw_video.write(grayscale_frame.to_colorspace().data)
- if output_video_to_file:
- output_video.write(show_frame)
+ # Export the processed frame to the output video file if needed
+ if output_processed_video is not None:
+ output_processed_video.write(show_frame.data)
+ # Show the processed frame in the visualization window if needed
if show_video_result:
- cv.imshow("Satellite detection", show_frame)
+ cv.imshow("Satellite detection", show_frame.data)
+ # Wait for the user input to change the visualization speed or exit the
+ # program
key = cv.waitKey(wait_time)
+ # Exit the program if the user pressed the 'q' key
if key == ord("q"):
+ print("Exit requested by user.")
break
+ # Update the visualization speed if the user pressed one of the speed keys
wait_time = wait_options.get(key, wait_time)
+ # Print the processing time statistics
print_time_statistics(processed_frames, start_time)
- export_satellite_log(satellite_log)
- if output_video_to_file:
- print(f"Video saved on '{str(PATH_OUTPUT_VIDEO)}'")
+ # Export the satellite log to a file if needed
+ if output_sat_log_to_file:
+ export_satellite_log(satellite_log, path_output_sat_log)
+
+ # Notify the user about the created output video files
+ if output_raw_video is not None:
+ print(f"Raw video saved on '{path_output_raw_video}'")
+ if output_processed_video is not None:
+ print(f"Processed video saved on '{path_output_processed_video}'")
+ # Release the resources and close the visualization window
+ input_stream.release()
cv.destroyAllWindows()
@@ -183,223 +237,37 @@ def print_time_statistics(
):
"""Function to print processing time statistics."""
- processing_time = perf_counter() - start_time
+ processing_time = time__perf_counter() - start_time
+ print("Processing time statistics:")
print(" Processed frames:", processed_frames)
print(" Time needed:", processing_time)
- print(" FPS:", processed_frames / processing_time)
- print()
+ print(" Estimated FPS:", processed_frames / processing_time)
-def draw_found_stars(
- show_frame,
- found_stars: list[tuple[int, int]],
- radius: int = PX_SENSITIVITY,
- color: tuple = (0, 0, 100),
- thickness: int = 2,
-):
- """
- Function to draw in the given frame a circle around every found star.
-
-
- Note: This function modifies data from 'show_frame' parameter without an explicit
- return statement for memory usage reduction purposes.
- """
-
- for star in found_stars:
- cv.circle(
- show_frame,
- center=(
- int(star[0]),
- int(star[1]),
- ),
- radius=radius,
- color=color,
- thickness=thickness,
- )
-
-
-def draw_tracked_stars(
- show_frame,
- tracked_stars: set[Star],
- radius: int = PX_SENSITIVITY,
- color: tuple = None,
- thickness: int = 2,
- colorized_tracked_stars: bool = COLORIZED_TRACKED_STARS,
-):
- """
- Function to draw in the given frame a circle around every tracked star.
-
-
- Note: This function modifies data from 'show_frame' parameter without an explicit
- return statement for memory usage reduction purposes.
- """
-
- for star in tracked_stars:
-
- if color is None:
- if colorized_tracked_stars:
- draw_color = star.color
- else:
- draw_color = (0, 0, 100)
- else:
- draw_color = color
-
- cv.circle(
- show_frame,
- center=(
- int(star.last_detected_position[0]),
- int(star.last_detected_position[1]),
- ),
- radius=radius,
- color=draw_color,
- thickness=thickness,
- )
-
-
-def draw_shooting_stars(
- show_frame,
- shooting_stars: set[Star],
- radius: int = PX_SENSITIVITY,
- color: tuple = (0, 200, 200),
- thickness: int = 2,
-):
- """
- Function to draw in the given frame a circle around every shooting star.
-
-
- Note: This function modifies data from 'show_frame' parameter without an explicit
- return statement for memory usage reduction purposes.
- """
-
- for star in shooting_stars:
- cv.circle(
- show_frame,
- center=(
- int(star.last_detected_position[0]),
- int(star.last_detected_position[1]),
- ),
- radius=radius,
- color=color,
- thickness=thickness,
- )
-
-
-def draw_satellite(
- show_frame,
- satellite: Star,
- radius: int = PX_SENSITIVITY,
- color: tuple = (0, 200, 0),
- thickness: int = 2,
-):
- """
- Function to draw in the given frame a circle around the detected satellite.
-
-
- Note: This function modifies data from 'show_frame' parameter without an explicit
- return statement for memory usage reduction purposes.
- """
-
- cv.circle(
- show_frame,
- center=(
- int(satellite.last_detected_position[0]),
- int(satellite.last_detected_position[1]),
- ),
- radius=radius,
- color=color,
- thickness=thickness,
- )
-
-
-def draw_path(
- show_frame,
- targets: Star | set[Star],
- color: tuple = (200, 200, 0),
- thickness: int = 1,
-):
- """
- Function to draw in the given frame a line through the last detected positions of
- the given objects.
-
-
- Note: This function modifies data from 'show_frame' parameter without an explicit
- return statement for memory usage reduction purposes.
- """
-
- for target in {targets} if isinstance(targets, Star) else targets:
- last_positions = [
- [round(axis) for axis in pos]
- for pos in target.last_positions
- if pos is not None
- ]
- for pos_1, pos_2 in pairwise(last_positions):
- cv.line(
- show_frame,
- pt1=pos_1,
- pt2=pos_2,
- color=color,
- thickness=thickness,
- )
-
-
-def draw_expected_position(
- show_frame,
- targets: Star | set[Star],
- radius: int = PX_SENSITIVITY,
- color: tuple = (200, 200, 0),
- thickness: int = 1,
-):
- """
- Function to draw in the given frame a circle around the expected position of the
- given objects.
-
-
- Note: This function modifies data from 'show_frame' parameter without an explicit
- return statement for memory usage reduction purposes.
- """
-
- for target in {targets} if isinstance(targets, Star) else targets:
- cv.circle(
- show_frame,
- center=(
- int(target.expected_position[0]),
- int(target.expected_position[1]),
- ),
- radius=radius,
- color=color,
- thickness=thickness,
- )
-
-
-def create_export_video_file(vid_cap):
+def create_export_video_file(input_stream, output_video_path: str):
"""Function to create a video file to export the processed frames."""
- width = int(vid_cap.get(cv.CAP_PROP_FRAME_WIDTH))
- height = int(vid_cap.get(cv.CAP_PROP_FRAME_HEIGHT))
- fps = int(vid_cap.get(cv.CAP_PROP_FPS))
- frame_count = int(vid_cap.get(cv.CAP_PROP_FRAME_COUNT))
-
- print(f"\nVideo format: {width}x{height} px - {fps} fps")
- print("Number of frames:", frame_count)
-
output_video = cv.VideoWriter(
- str(PATH_OUTPUT_VIDEO),
+ output_video_path,
cv.VideoWriter_fourcc(*"mp4v"),
- fps,
- (width, height),
+ input_stream.fps,
+ (input_stream.frame_width, input_stream.frame_height),
)
if not output_video.isOpened():
- sys.exit("\nError: Unable to create video file.")
+ sys__exit("\nError: Unable to create video file.")
return output_video
-def export_satellite_log(satellite_log: list[Star]):
+def export_satellite_log(
+ satellite_log: list[Star],
+ path_output_sat_log: str = str(PATH_OUTPUT_SAT_LOG),
+):
"""Function to export the satellite log into a file."""
- with open(str(PATH_SAT_LOG), "w", encoding="utf-8-sig") as file:
+ with open(path_output_sat_log, "w", encoding="utf-8-sig") as file:
print(
"id;",
"last_times_detected;",
@@ -410,7 +278,8 @@ def export_satellite_log(satellite_log: list[Star]):
"movement_vector;",
"frames_since_last_detection;",
"last_detected_position;",
- "expected_position;",
+ "next_expected_position;",
+ "last_predicted_position",
"last_positions;",
file=file,
)
@@ -426,7 +295,8 @@ def export_satellite_log(satellite_log: list[Star]):
f"{star.movement_vector};",
f"{star.frames_since_last_detection};",
f"{star.last_detected_position};",
- f"{star.expected_position};",
+ f"{star.next_expected_position};",
+ f"{star.last_predicted_position};",
f"{star.last_positions};",
file=file,
)
diff --git a/requirements.txt b/requirements.txt
index cb3738c..9de5bab 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -1,2 +1,7 @@
-numpy
-opencv-python
+coverage==7.3.2
+imutils==0.5.4
+numpy==1.26.4
+opencv-python==4.8.1.78
+pillow==10.3.0
+tensorflow==2.18.0
+zwoasi==0.2.0
diff --git a/src/image_frame.py b/src/image_frame.py
new file mode 100644
index 0000000..1722666
--- /dev/null
+++ b/src/image_frame.py
@@ -0,0 +1,256 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+File with the implementation of the ImageFrame class.
+"""
+
+from copy import deepcopy
+from itertools import pairwise as itertools__pairwise
+
+import cv2 as cv
+from imutils import translate as imutils__translate
+import numpy as np
+
+from src.star import Star
+from constants import (
+ MARK_DETECTED_STARS,
+ MARK_TRACKED_STARS,
+ MARK_SHOOTING_STARS,
+ MARK_SATELLITE,
+ MARK_MOVEMENT_VECTOR,
+ MARK_NEXT_EXPECTED_POSITION,
+ MARK_LAST_PREDICTED_POSITION,
+ COLORIZED_TRACKED_STARS,
+ MARK_POSITION_DEFAULT_COLOR,
+ MARK_SHOOTING_STAR_COLOR,
+ MARK_SATELLITE_COLOR,
+ MARK_NEXT_EXPECTED_POSITION_COLOR,
+ MARK_LAST_PREDICTED_POSITION_COLOR,
+ MARK_MOVEMENT_VECTOR_COLOR,
+ MARK_RADIUS,
+ MARK_THICKNESS,
+)
+
+
+class ImageFrame:
+ def __init__(
+ self,
+ data: cv.mat_wrapper.Mat | np.ndarray,
+ width: int = None,
+ height: int = None,
+ is_color: bool = None,
+ ):
+ self.data = data.copy()
+ self.width = width if width is not None else data.shape[1]
+ self.height = height if height is not None else data.shape[0]
+
+ if is_color is not None:
+ self.is_color = is_color
+ else:
+ self.is_color = len(data.shape) == 3 and data.shape[2] == 3
+
+ self.frame_center = (self.width / 2, self.height / 2)
+
+ def copy(self):
+ """Method to return a deep copy of the current ImageFrame object."""
+
+ return deepcopy(self)
+
+ def to_grayscale(self) -> "ImageFrame":
+ """Method to convert the current image frame to grayscale color space."""
+
+ if self.is_color:
+ return ImageFrame(
+ cv.cvtColor(self.data, cv.COLOR_BGR2GRAY),
+ width=self.width,
+ height=self.height,
+ is_color=False,
+ )
+
+ else:
+ return self.copy()
+
+ def to_colorspace(self) -> "ImageFrame":
+ """Method to convert the current image frame to RGB color space."""
+
+ if self.is_color:
+ return self.copy()
+
+ else:
+ return ImageFrame(
+ cv.cvtColor(self.data, cv.COLOR_GRAY2BGR),
+ width=self.width,
+ height=self.height,
+ is_color=True,
+ )
+
+ def mark_position(
+ self,
+ target: tuple[int, int],
+ color: tuple = MARK_POSITION_DEFAULT_COLOR,
+ radius: int = MARK_RADIUS,
+ thickness: int = MARK_THICKNESS,
+ ):
+ """Method to mark in the frame data a circle around the given position."""
+
+ cv.circle(
+ self.data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ def mark_path(
+ self,
+ targets: Star | set[Star],
+ color: tuple = MARK_MOVEMENT_VECTOR_COLOR,
+ thickness: int = MARK_THICKNESS,
+ ):
+ """
+ Method to mark in the frame data a line through the last detected positions of
+ the given objects.
+ """
+
+ for target in {targets} if isinstance(targets, Star) else targets:
+ last_positions = [
+ [round(axis) for axis in pos]
+ for pos in target.last_positions
+ if pos is not None
+ ]
+ for pos_1, pos_2 in itertools__pairwise(last_positions):
+ cv.line(
+ self.data,
+ pt1=pos_1,
+ pt2=pos_2,
+ color=color,
+ thickness=thickness,
+ )
+
+ def mark(
+ self,
+ new_star_positions: list[tuple[int, int]] = None,
+ tracked_stars: set[Star] = None,
+ shooting_stars: set[Star] = None,
+ satellite: Star = None,
+ mark_new_stars: bool = MARK_DETECTED_STARS,
+ mark_tracked_stars: bool = MARK_TRACKED_STARS,
+ mark_shooting_stars: bool = MARK_SHOOTING_STARS,
+ mark_satellite: bool = MARK_SATELLITE,
+ mark_movement_vector: bool = MARK_MOVEMENT_VECTOR,
+ mark_next_expected_position: bool = MARK_NEXT_EXPECTED_POSITION,
+ mark_last_predicted_position: bool = MARK_LAST_PREDICTED_POSITION,
+ colorized_tracked_stars: bool = COLORIZED_TRACKED_STARS,
+ mark_position_default_color: tuple = MARK_POSITION_DEFAULT_COLOR,
+ mark_shooting_star_color: tuple = MARK_SHOOTING_STAR_COLOR,
+ mark_satellite_color: tuple = MARK_SATELLITE_COLOR,
+ mark_next_expected_position_color: tuple = MARK_NEXT_EXPECTED_POSITION_COLOR,
+ mark_last_predicted_position_color: tuple = MARK_LAST_PREDICTED_POSITION_COLOR,
+ mark_radius: int = MARK_RADIUS,
+ mark_thickness: int = MARK_THICKNESS,
+ ):
+ """Method to mark information about the detected elements in the frame data."""
+
+ if mark_new_stars and new_star_positions is not None:
+ for star in new_star_positions:
+ self.mark_position(
+ star,
+ color=mark_position_default_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+
+ if mark_tracked_stars and tracked_stars is not None:
+ for star in tracked_stars:
+ if colorized_tracked_stars and isinstance(star, Star):
+ self.mark_position(
+ star.last_detected_position,
+ color=star.color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+ else:
+ self.mark_position(
+ star.last_detected_position,
+ color=mark_position_default_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+
+ if mark_shooting_stars and shooting_stars is not None:
+ for star in shooting_stars:
+ if mark_movement_vector:
+ self.mark_path(star)
+
+ self.mark_position(
+ star.last_detected_position,
+ color=mark_shooting_star_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+
+ if mark_next_expected_position:
+ self.mark_position(
+ star.next_expected_position,
+ color=mark_next_expected_position_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+ if mark_last_predicted_position:
+ self.mark_position(
+ star.last_predicted_position,
+ color=mark_last_predicted_position_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+
+ if mark_satellite and satellite is not None:
+ if mark_movement_vector:
+ self.mark_path(satellite)
+
+ self.mark_position(
+ satellite.last_detected_position,
+ color=mark_satellite_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+
+ if mark_next_expected_position:
+ self.mark_position(
+ satellite.next_expected_position,
+ color=mark_next_expected_position_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+ if mark_last_predicted_position:
+ self.mark_position(
+ satellite.last_predicted_position,
+ color=mark_last_predicted_position_color,
+ radius=mark_radius,
+ thickness=mark_thickness,
+ )
+
+ def tracking_phase_video_simulation(self, satellite: Star):
+ """
+ Method to simulate the tracking phase of the satellite by moving the frame data
+ to set the target satellite in the center of the video.
+
+
+ Caution: This method does not modify the relative positions of the detected
+ objects in the frame, later modifications should be done to keep the objects
+ in the correct positions if required.
+ """
+
+ translation_vector = [
+ self.frame_center[0] - satellite.next_expected_position[0],
+ self.frame_center[1] - satellite.next_expected_position[1],
+ ]
+
+ self.data = imutils__translate(
+ self.data,
+ translation_vector[0],
+ translation_vector[1],
+ )
diff --git a/src/image_processor.py b/src/image_processor.py
index 7e48737..611de6a 100644
--- a/src/image_processor.py
+++ b/src/image_processor.py
@@ -8,35 +8,131 @@
from math import dist
from typing import Optional
+import cv2 as cv
+import numpy as np
+import tensorflow as tf
+from tensorflow import keras
+
+from src.image_frame import ImageFrame
from src.star import Star
from constants import (
- FAST,
- MIN_PRUNE_DISTANCE,
- SAT_DESIRED_BLINKING_FREQ,
VIDEO_FPS,
+ STAR_DETECTION_MODE,
+ STAR_DETECTOR_THRESHOLD,
+ NEURAL_NETWORK_MODEL_PATH,
+ PRUNE_CLOSE_POINTS,
+ MIN_PRUNE_DISTANCE,
DEFAULT_LEFT_LIFETIME,
+ SAT_DESIRED_BLINKING_FREQ,
+ MIN_DETECTION_CONFIDENCE,
DEFAULT_VECTOR,
MOVEMENT_THRESHOLD,
- MIN_DETECTION_CONFIDENCE,
)
+def load_star_detector(
+ star_detection_mode: str = STAR_DETECTION_MODE,
+ star_detector_threshold: int = STAR_DETECTOR_THRESHOLD,
+ neural_network_model_path: str = NEURAL_NETWORK_MODEL_PATH,
+):
+
+ if star_detection_mode == "OPEN_CV":
+ star_detector = cv.FastFeatureDetector_create(threshold=star_detector_threshold)
+
+ elif star_detection_mode == "NEURAL_NETWORK":
+ star_detector = keras.models.load_model(neural_network_model_path)
+
+ else:
+ raise ValueError(f"Invalid star detector mode: {star_detection_mode}")
+
+ return star_detector
+
+
+def detect_sky_objects(input_image, model, input_tensor_shape=(256, 256)):
+ """Function to apply the model inference over the given image."""
+
+ # Adapt the input image to the model input shape and format
+ resized_image = cv.resize(input_image, dsize=input_tensor_shape)
+ input_tensor = tf.convert_to_tensor([resized_image])
+
+ # Apply the model to the input image
+ predicted_mask = model.predict(input_tensor)[0]
+
+ # Reverse the one-hot encoding to create a single segmentation mask
+ segmentation_mask = np.argmax(predicted_mask, axis=-1)
+
+ # Resize the mask to the original image size
+ result_mask = cv.resize(
+ segmentation_mask.astype(np.uint8),
+ dsize=(input_image.shape[1], input_image.shape[0]),
+ )
+
+ return result_mask
+
+
+def get_sky_objects_positions(segmentation_mask):
+ """
+ Function to get the central positions of the detected objects at the given
+ segmentation mask.
+ """
+
+ # Get the contours of each detected region
+ contours, _ = cv.findContours(
+ segmentation_mask,
+ cv.RETR_LIST,
+ cv.CHAIN_APPROX_SIMPLE,
+ )
+
+ min_detected_object_size = 10
+ sky_objects_positions = []
+ for contour in contours:
+ if cv.contourArea(contour) < min_detected_object_size:
+ continue
+
+ # Get the bounding box of each contour
+ corner_x_coord, corner_y_coord, width, height = cv.boundingRect(contour)
+
+ # Get the center of the bounding box
+ center_x_coord = corner_x_coord + width / 2
+ center_y_coord = corner_y_coord + height / 2
+
+ # Add the center coordinates to the list of detected objects positions
+ sky_objects_positions.append((center_x_coord, center_y_coord))
+
+ return sky_objects_positions
+
+
def detect_stars(
- image,
+ image_frame: ImageFrame,
star_detector,
- fast: bool = FAST,
+ star_detection_mode: str = STAR_DETECTION_MODE,
+ prune_close_points: bool = PRUNE_CLOSE_POINTS,
min_prune_distance: float = MIN_PRUNE_DISTANCE,
) -> list[tuple[int, int]]:
"""Function to get all the bright points of a given image."""
- keypoints = star_detector.detect(image, None)
- points = [keypoint.pt for keypoint in keypoints]
+ if star_detection_mode == "OPEN_CV":
+ keypoints = star_detector.detect(image_frame.data, None)
+ points = [keypoint.pt for keypoint in keypoints]
+
+ elif star_detection_mode == "NEURAL_NETWORK":
+ inference_result_mask = detect_sky_objects(
+ image_frame.data, star_detector
+ ).astype(np.uint8)
+ points = get_sky_objects_positions(inference_result_mask)
- return points if fast else prune_close_points(points, min_prune_distance)
+ else:
+ raise ValueError(f"Invalid star detector mode: {star_detection_mode}")
+
+ return (
+ _prune_close_points(points, min_prune_distance)
+ if prune_close_points
+ else points
+ )
-def prune_close_points(
+def _prune_close_points(
points: list[tuple[int, int]],
min_prune_distance: float = MIN_PRUNE_DISTANCE,
) -> list[tuple[int, int]]:
diff --git a/src/input_stream.py b/src/input_stream.py
new file mode 100644
index 0000000..a946d62
--- /dev/null
+++ b/src/input_stream.py
@@ -0,0 +1,163 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+File with the implementation of the InputStream class.
+"""
+
+from os import getenv as os__get_env_var
+from pathlib import Path
+from sys import exit as sys__exit
+
+import cv2 as cv
+import zwoasi
+
+from constants import (
+ SOURCE_TYPE,
+ CAMERA_INDEX,
+ PATH_INPUT_VIDEO,
+ VIDEO_FPS, # ToDo: Try to get from input source
+)
+from src.image_frame import ImageFrame
+
+
+class InputStream:
+ def __init__(
+ self,
+ source_type: str = SOURCE_TYPE,
+ camera_index: int = CAMERA_INDEX,
+ path_input_video: Path = PATH_INPUT_VIDEO,
+ ):
+ self.source_type = source_type
+ self.camera_index = camera_index
+ self.path_input_video = path_input_video
+
+ self._input_stream = None
+
+ if source_type == "ZWOASI":
+ self.__init__zwo_asi_camera__()
+
+ elif source_type == "WEBCAM":
+ print(f"Initializing webcam #{self.camera_index} using OpenCV")
+ self.__init__opencv_video_capture__(self.camera_index)
+
+ elif source_type == "VIDEO_FILE":
+ print(f"Processing video from: {self.path_input_video} using OpenCV")
+ self.__init__opencv_video_capture__(str(self.path_input_video))
+
+ else:
+ sys__exit("\nError: Invalid source type.")
+
+ def __init__zwo_asi_camera__(self):
+ """Method to initialize the ZWO ASI camera."""
+
+ zwo_asi_lib = os__get_env_var("ZWO_ASI_LIB")
+ zwoasi.init(zwo_asi_lib)
+
+ if not zwoasi.get_num_cameras():
+ print("No cameras found")
+ exit(0)
+
+ print(f"Initializing ZWO ASI camera #{self.camera_index}")
+ self._input_stream = zwoasi.Camera(self.camera_index)
+
+ # Get camera information
+ self.zwo_camera_info = self._input_stream.get_camera_property()
+
+ print("Camera info:")
+ for k, v in self.zwo_camera_info.items():
+ print(f" {k}: {v}")
+
+ self.is_color_camera = self.zwo_camera_info["IsColorCam"]
+ self.fps = VIDEO_FPS # ToDo: value not available, may have to be calculated
+
+ # Get frame dimensions and calculate its center
+ self.frame_width = self.zwo_camera_info["MaxWidth"]
+ self.frame_height = self.zwo_camera_info["MaxHeight"]
+
+ # Use minimum USB bandwidth permitted
+ self._input_stream.set_control_value(
+ zwoasi.ASI_BANDWIDTHOVERLOAD,
+ self._input_stream.get_controls()["BandWidth"]["MinValue"],
+ )
+
+ # Set some sensible defaults. They will need adjusting depending upon
+ # the sensitivity, lens and lighting conditions used.
+ self._input_stream.disable_dark_subtract()
+
+ # ToDo: extract setting values to parameters and enable modifications on the fly
+ self._input_stream.set_control_value(zwoasi.ASI_GAIN, 200)
+ self._input_stream.set_control_value(zwoasi.ASI_EXPOSURE, 500)
+ self._input_stream.set_control_value(zwoasi.ASI_WB_B, 99)
+ self._input_stream.set_control_value(zwoasi.ASI_WB_R, 75)
+ self._input_stream.set_control_value(zwoasi.ASI_GAMMA, 50)
+ self._input_stream.set_control_value(zwoasi.ASI_BRIGHTNESS, 50)
+ self._input_stream.set_control_value(zwoasi.ASI_FLIP, 0)
+
+ print("Enabling video mode")
+ self._input_stream.start_video_capture()
+
+ # Set the timeout, units are ms
+ timeout = (
+ self._input_stream.get_control_value(zwoasi.ASI_EXPOSURE)[0] / 1000
+ ) * 2 + 500 # ToDo: Decrypt this values and adjust them for better FPS
+ self._input_stream.default_timeout = timeout
+
+ def __init__opencv_video_capture__(self, ocv_video_source):
+ """Method to initialize the OpenCV video capture."""
+
+ self._input_stream = cv.VideoCapture(ocv_video_source)
+
+ if not self._input_stream.isOpened():
+ sys__exit("\nError: Unable to open video source.")
+
+ # get if camera captures color or monochrome based on the number of channels of
+ # the first frame; if 3, it is color; if 1, it is monochrome
+ self.is_color_camera = self._input_stream.read()[1].shape[2] == 3
+
+ self.fps = int(self._input_stream.get(cv.CAP_PROP_FPS))
+
+ self.frame_width = int(self._input_stream.get(cv.CAP_PROP_FRAME_WIDTH))
+ self.frame_height = int(self._input_stream.get(cv.CAP_PROP_FRAME_HEIGHT))
+
+ def get_next_frame(self):
+ """Method to get the next frame from the input stream."""
+
+ if self.source_type == "ZWOASI":
+ try:
+ return ImageFrame(
+ self._input_stream.capture_video_frame(),
+ self.frame_width,
+ self.frame_height,
+ self.is_color_camera,
+ )
+ except zwoasi.ZWO_IOError:
+ return None
+
+ elif self.source_type == "WEBCAM" or self.source_type == "VIDEO_FILE":
+ success, next_frame = self._input_stream.read()
+ return (
+ ImageFrame(
+ next_frame,
+ self.frame_width,
+ self.frame_height,
+ self.is_color_camera,
+ )
+ if success
+ else None
+ )
+
+ else:
+ sys__exit("\nError: Invalid source type.")
+
+ def release(self):
+ """Method to release the resources of the input stream."""
+
+ if self.source_type == "ZWOASI":
+ self._input_stream.stop_video_capture()
+ self._input_stream.close()
+
+ elif self.source_type == "WEBCAM" or self.source_type == "VIDEO_FILE":
+ self._input_stream.release()
+
+ else:
+ sys__exit("\nError: Invalid source type.")
diff --git a/src/star.py b/src/star.py
index 0312c21..695e11d 100644
--- a/src/star.py
+++ b/src/star.py
@@ -11,16 +11,17 @@
from typing import Generator, Optional
from constants import (
- SAT_DESIRED_BLINKING_FREQ,
VIDEO_FPS,
DEFAULT_LEFT_LIFETIME,
+ MAX_HISTORY_LENGTH,
+ SAT_DESIRED_BLINKING_FREQ,
+ FREQUENCY_THRESHOLD,
DEFAULT_VECTOR,
MIN_HISTORY_LENGTH,
- MAX_HISTORY_LENGTH,
REMOVE_OUTLIERS,
MAX_OUTLIER_THRESHOLD,
MAX_MOVE_DISTANCE,
- FREQUENCY_THRESHOLD,
+ MOVEMENT_VECTOR_COMPUTATION_METHOD,
)
random.seed(time())
@@ -37,6 +38,7 @@ def id_generator() -> Generator:
next_id += 1
+# @dataclass # ToDo: test if implementing dataclass does not lead to a loss of performance
class Star:
"""Class to represent a detected star (or satellite) and save its data for tracking
purposes."""
@@ -55,7 +57,8 @@ def __init__(
color: list[int] = None,
frames_since_last_detection: int = None,
last_detected_position: tuple[int, int] = None,
- expected_position: tuple[int, int] = None,
+ next_expected_position: tuple[int, int] = None,
+ last_predicted_position: tuple[int, int] = None,
):
self.id = next(self._id)
@@ -84,7 +87,15 @@ def __init__(
if frames_since_last_detection is not None:
self.frames_since_last_detection = frames_since_last_detection
- self.expected_position = self.get_new_expected_position(expected_position)
+ self.next_expected_position = self.get_new_expected_position(
+ next_expected_position
+ )
+
+ self.last_predicted_position = (
+ last_predicted_position
+ if last_predicted_position is not None
+ else self.next_expected_position
+ )
def __hash__(self) -> int:
"""Function to set the star's id as the object's hash value."""
@@ -112,6 +123,7 @@ def update_info(
max_outlier_threshold: float = MAX_OUTLIER_THRESHOLD,
default_vector: tuple[float, float] = DEFAULT_VECTOR,
frequency_threshold: float = FREQUENCY_THRESHOLD,
+ movement_vector_computation_method: str = MOVEMENT_VECTOR_COMPUTATION_METHOD,
) -> None:
"""
Function to update the star's information.
@@ -141,6 +153,7 @@ def update_info(
self.left_lifetime = default_left_lifetime
self.frames_since_last_detection = 1
self.last_detected_position = new_star_pos
+ self.last_predicted_position = self.next_expected_position
self.last_positions = self.last_positions[-max_history_length:]
self.last_times_detected = self.last_times_detected[-max_history_length:]
@@ -152,8 +165,9 @@ def update_info(
remove_outliers,
max_outlier_threshold,
default_vector,
+ movement_vector_computation_method,
)
- self.expected_position = self.get_new_expected_position()
+ self.next_expected_position = self.get_new_expected_position()
self.blinking_freq = video_fps * (
sum(self.last_times_detected) / len(self.last_times_detected)
@@ -185,15 +199,15 @@ def get_new_star_position(
return None
try:
- star_positions.index(self.expected_position)
- return self.expected_position
+ star_positions.index(self.next_expected_position)
+ return self.next_expected_position
except ValueError:
new_star_pos = None
best_candidate_dist = max_move_distance
for current_star_pos in star_positions:
- current_pair_dist = dist(self.expected_position, current_star_pos)
+ current_pair_dist = dist(self.next_expected_position, current_star_pos)
if current_pair_dist < best_candidate_dist:
best_candidate_dist = current_pair_dist
@@ -207,6 +221,7 @@ def get_new_movement_vector(
remove_outliers: bool = REMOVE_OUTLIERS,
max_outlier_threshold: float = MAX_OUTLIER_THRESHOLD,
default_vector: tuple[float, float] = DEFAULT_VECTOR,
+ movement_vector_computation_method: str = MOVEMENT_VECTOR_COMPUTATION_METHOD,
) -> tuple[float, float]:
"""Function to calculate the star movement vector based on its last detected
positions."""
@@ -215,7 +230,11 @@ def get_new_movement_vector(
return default_vector
movement_vectors = self.get_individual_movement_vectors()
- mean_vector = get_mean_vector(movement_vectors, default_vector)
+ mean_vector = get_average_vector(
+ movement_vectors,
+ default_vector,
+ movement_vector_computation_method,
+ )
if not remove_outliers:
return mean_vector
@@ -226,7 +245,11 @@ def get_new_movement_vector(
if dist(mean_vector, current_vector) < max_outlier_threshold
]
- return get_mean_vector(filtered_vectors, default_vector)
+ return get_average_vector(
+ filtered_vectors,
+ default_vector,
+ movement_vector_computation_method,
+ )
def get_individual_movement_vectors(self) -> list[tuple[float, float]]:
"""Function to get the individual movement vectors between each pair of its last
@@ -314,20 +337,83 @@ def get_new_last_detected_position(
return None
-def get_mean_vector(
+# ToDo: extract this to another file?
+# ToDo: test the different methods and compare accuracy and performance
+def get_average_vector(
vectors: list[tuple[float, float]],
default_vector: tuple[float, float] = DEFAULT_VECTOR,
+ computation_method: str = MOVEMENT_VECTOR_COMPUTATION_METHOD,
) -> tuple[float, float]:
- """Function to calculate the mean vector of the given list of vectors."""
+ """
+ Function to calculate the average (or central tendency) vector from the given list.
+
+
+ The 'computation_method' parameter can be used to select how to calculate the
+ resulting vector.
+
+ - mean: arithmetic mean
+ - median: middle value after sorting
+ - mode: most common value
+
+
+ If the given list of vectors is empty then the 'default_vector' is returned.
+ """
num_of_vectors = len(vectors)
- if num_of_vectors != 0:
- zipped_points = list(zip(*vectors))
+ if num_of_vectors == 0:
+ return default_vector
+
+ zipped_points = list(zip(*vectors))
+ if computation_method == "mean":
+ # return the mean of each axis
return (
sum(zipped_points[0]) / num_of_vectors,
sum(zipped_points[1]) / num_of_vectors,
)
- return default_vector
+ elif computation_method == "median":
+ # return the median of each axis
+ center_index = num_of_vectors // 2
+ sorted_zipped_points = [
+ sorted(zipped_points[0]),
+ sorted(zipped_points[1]),
+ ]
+
+ if num_of_vectors % 2 == 0:
+ return (
+ (
+ (
+ (sorted_zipped_points[0][center_index - 1])
+ + (sorted_zipped_points[0][center_index])
+ )
+ / 2
+ ),
+ (
+ (
+ (sorted_zipped_points[1][center_index - 1])
+ + (sorted_zipped_points[1][center_index])
+ )
+ / 2
+ ),
+ )
+
+ else:
+ return (
+ sorted_zipped_points[0][center_index],
+ sorted_zipped_points[1][center_index],
+ )
+
+ elif computation_method == "mode":
+ # return the mode of each axis
+ return (
+ max(set(zipped_points[0]), key=zipped_points[0].count),
+ max(set(zipped_points[1]), key=zipped_points[1].count),
+ )
+
+ else:
+ raise ValueError(
+ "Error: Invalid computation method, "
+ + "the available values are: 'mean', 'median' and 'mode'"
+ )
diff --git a/test/test_image_frame.py b/test/test_image_frame.py
new file mode 100644
index 0000000..655d870
--- /dev/null
+++ b/test/test_image_frame.py
@@ -0,0 +1,1077 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+This program tests the correct functionality of the functions at src/image_frame.py
+ file.
+"""
+
+
+import unittest
+
+import cv2 as cv
+import numpy as np
+
+from src.image_frame import (
+ ImageFrame,
+ MARK_POSITION_DEFAULT_COLOR,
+ MARK_SHOOTING_STAR_COLOR,
+ MARK_SATELLITE_COLOR,
+ MARK_NEXT_EXPECTED_POSITION_COLOR,
+ MARK_LAST_PREDICTED_POSITION_COLOR,
+ MARK_MOVEMENT_VECTOR_COLOR,
+ MARK_RADIUS,
+ MARK_THICKNESS,
+)
+from src.star import Star
+
+
+class ImageFrameClassTestCase(unittest.TestCase):
+ """Class to test the ImageFrame class and its methods."""
+
+ def test_simple_image_frame_1(self):
+ """A simple image frame can be created only with basic frame data."""
+
+ data = np.array(
+ [
+ [1, 2],
+ [3, 4],
+ [5, 6],
+ ],
+ )
+
+ image_frame = ImageFrame(data)
+
+ self.assertTrue(np.array_equal(data, image_frame.data))
+ self.assertEqual(image_frame.width, 2)
+ self.assertEqual(image_frame.height, 3)
+ self.assertEqual(image_frame.is_color, False)
+
+ def test_simple_image_frame_2(self):
+ """A simple image frame can be created with optional arguments."""
+
+ data = np.array(
+ [
+ [1, 2, 3],
+ [4, 5, 6],
+ ],
+ )
+
+ image_frame = ImageFrame(
+ data,
+ width=data.shape[1],
+ height=data.shape[0],
+ is_color=(len(data.shape) == 3 and data.shape[2] == 3),
+ )
+
+ self.assertTrue(np.array_equal(data, image_frame.data))
+ self.assertEqual(image_frame.width, 3)
+ self.assertEqual(image_frame.height, 2)
+ self.assertEqual(image_frame.is_color, False)
+
+ def test_real_image_frame_1(self):
+ """
+ A color image frame can be created from a real color image only with basic frame
+ data.
+ """
+
+ image_data = cv.imread("./data/images/original.jpg")
+ image_frame = ImageFrame(image_data)
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+ self.assertEqual(image_frame.width, 1280)
+ self.assertEqual(image_frame.height, 720)
+ self.assertEqual(image_frame.is_color, True)
+
+ def test_real_image_frame_2(self):
+ """
+ A grayscale image frame can be created from a real grayscale image only with
+ basic frame data.
+ """
+
+ grayscale_image_data = cv.cvtColor(
+ cv.imread("./data/images/original.jpg"), cv.COLOR_BGR2GRAY
+ )
+ image_frame = ImageFrame(grayscale_image_data)
+
+ self.assertTrue(np.array_equal(grayscale_image_data, image_frame.data))
+ self.assertEqual(image_frame.width, 1280)
+ self.assertEqual(image_frame.height, 720)
+ self.assertEqual(image_frame.is_color, False)
+
+ def test_real_image_frame_3(self):
+ """An image frame can be created from a real image with optional arguments."""
+
+ image_data = cv.imread("./data/images/original.jpg")
+ image_frame = ImageFrame(
+ image_data,
+ width=image_data.shape[1],
+ height=image_data.shape[0],
+ is_color=(len(image_data.shape) == 3 and image_data.shape[2] == 3),
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+ self.assertEqual(image_frame.width, 1280)
+ self.assertEqual(image_frame.height, 720)
+ self.assertEqual(image_frame.is_color, True)
+
+ def test_copy(self):
+ """A copy of an image frame will return a new image frame with the same data."""
+
+ original_image_frame = ImageFrame(cv.imread("./data/images/original.jpg"))
+ copied_image_frame = original_image_frame.copy()
+
+ self.assertTrue(
+ np.array_equal(original_image_frame.data, copied_image_frame.data)
+ )
+ self.assertEqual(original_image_frame.width, copied_image_frame.width)
+ self.assertEqual(original_image_frame.height, copied_image_frame.height)
+ self.assertEqual(original_image_frame.is_color, copied_image_frame.is_color)
+
+ def test_to_grayscale_1(self):
+ """A color image frame can be converted to grayscale."""
+
+ image_data = cv.imread("./data/images/original.jpg")
+ image_frame = ImageFrame(image_data)
+ grayscale_image_frame = image_frame.to_grayscale()
+
+ self.assertTrue(
+ np.array_equal(
+ cv.cvtColor(image_data, cv.COLOR_BGR2GRAY), grayscale_image_frame.data
+ )
+ )
+ self.assertEqual(grayscale_image_frame.width, 1280)
+ self.assertEqual(grayscale_image_frame.height, 720)
+ self.assertEqual(grayscale_image_frame.is_color, False)
+
+ def test_to_grayscale_2(self):
+ """
+ A grayscale image frame will return a copy of itself when converted to
+ grayscale.
+ """
+
+ grayscale_image_data = cv.cvtColor(
+ cv.imread("./data/images/original.jpg"), cv.COLOR_BGR2GRAY
+ )
+ image_frame = ImageFrame(grayscale_image_data)
+ grayscale_image_frame = image_frame.to_grayscale()
+
+ self.assertTrue(
+ np.array_equal(grayscale_image_data, grayscale_image_frame.data)
+ )
+ self.assertEqual(grayscale_image_frame.width, 1280)
+ self.assertEqual(grayscale_image_frame.height, 720)
+ self.assertEqual(grayscale_image_frame.is_color, False)
+
+ def test_to_colorspace_1(self):
+ """A grayscale image frame can be converted to a color image frame."""
+
+ grayscale_image_data = cv.cvtColor(
+ cv.imread("./data/images/original.jpg"), cv.COLOR_BGR2GRAY
+ )
+ image_frame = ImageFrame(grayscale_image_data)
+ color_image_frame = image_frame.to_colorspace()
+
+ self.assertTrue(
+ np.array_equal(
+ cv.cvtColor(grayscale_image_data, cv.COLOR_GRAY2BGR),
+ color_image_frame.data,
+ )
+ )
+ self.assertEqual(color_image_frame.width, 1280)
+ self.assertEqual(color_image_frame.height, 720)
+ self.assertEqual(color_image_frame.is_color, True)
+
+ def test_to_colorspace_2(self):
+ """
+ A color image frame will return a copy of itself when converted to colorspace.
+ """
+
+ image_data = cv.imread("./data/images/original.jpg")
+ image_frame = ImageFrame(image_data)
+ color_image_frame = image_frame.to_colorspace()
+
+ self.assertTrue(np.array_equal(image_data, color_image_frame.data))
+ self.assertEqual(color_image_frame.width, 1280)
+ self.assertEqual(color_image_frame.height, 720)
+ self.assertEqual(color_image_frame.is_color, True)
+
+ def test_mark_position_1(self):
+ """
+ A circle can be drawn around a point in an image frame with default values.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (25, 25)
+
+ image_frame.mark_position(target)
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_POSITION_DEFAULT_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_position_2(self):
+ """A circle can be drawn around a point in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (25, 25)
+ color = (0, 0, 255)
+ radius = 10
+ thickness = 3
+
+ image_frame.mark_position(
+ target=target,
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_path_1(self):
+ """A line can be drawn in an image frame with default values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (10, 15)
+ end = (40, 35)
+
+ star = Star(last_positions=[start, end])
+ image_frame.mark_path(star)
+
+ cv.line(
+ image_data,
+ pt1=start,
+ pt2=end,
+ color=MARK_MOVEMENT_VECTOR_COLOR,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_path_2(self):
+ """A line can be drawn in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (10, 15)
+ end = (40, 35)
+ color = (0, 255, 0)
+ thickness = 3
+
+ star = Star(last_positions=[start, end])
+ image_frame.mark_path(star, color=color, thickness=thickness)
+
+ cv.line(
+ image_data,
+ pt1=start,
+ pt2=end,
+ color=color,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_path_3(self):
+ """
+ A line can be drawn in an image frame for a star with multiple last positions.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ positions = [(10, 15), (20, 35), (30, 25), (40, 35)]
+
+ star = Star(last_positions=positions)
+ image_frame.mark_path(star)
+
+ for start, end in zip(positions[:-1], positions[1:]):
+ cv.line(
+ image_data,
+ pt1=start,
+ pt2=end,
+ color=MARK_MOVEMENT_VECTOR_COLOR,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_path_4(self):
+ """
+ Multiple lines can be drawn in an image frame for multiple stars with different
+ last positions.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ positions_1 = [(10, 15), (20, 35), (30, 25), (40, 35)]
+ positions_2 = [(20, 25), (30, 45), (40, 35), (10, 45)]
+
+ stars = {
+ Star(last_positions=positions_1),
+ Star(last_positions=positions_2),
+ }
+
+ image_frame.mark_path(stars)
+
+ for star in stars:
+ for start, end in zip(star.last_positions[:-1], star.last_positions[1:]):
+ cv.line(
+ image_data,
+ pt1=start,
+ pt2=end,
+ color=MARK_MOVEMENT_VECTOR_COLOR,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_new_stars_1(self):
+ """A new star position can be marked in an image frame with default values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (25, 25)
+
+ image_frame.mark(
+ new_star_positions=[target],
+ mark_new_stars=True,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_POSITION_DEFAULT_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_new_stars_2(self):
+ """A new star position can be marked in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (25, 25)
+ color = (0, 0, 100)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ new_star_positions=[target],
+ mark_new_stars=True,
+ mark_position_default_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_new_stars_3(self):
+ """
+ Multiple new star positions can be marked in an image frame with default values.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(25, 25), (30, 30), (35, 35)]
+
+ image_frame.mark(
+ new_star_positions=targets,
+ mark_new_stars=True,
+ )
+
+ for target in targets:
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_POSITION_DEFAULT_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_new_stars_4(self):
+ """
+ Multiple new star positions can be marked in an image frame with custom values.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(25, 25), (30, 30), (35, 35)]
+ color = (0, 0, 100)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ new_star_positions=targets,
+ mark_new_stars=True,
+ mark_position_default_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ for target in targets:
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_tracked_stars_1(self):
+ """A tracked star can be marked in an image frame with default values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (30, 30)
+
+ image_frame.mark(
+ tracked_stars={Star(last_positions=[target])},
+ mark_tracked_stars=True,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_POSITION_DEFAULT_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_tracked_stars_2(self):
+ """A tracked star can be marked in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (30, 30)
+ color = (0, 0, 100)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ tracked_stars={Star(last_positions=[target])},
+ mark_tracked_stars=True,
+ mark_position_default_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_tracked_stars_3(self):
+ """Multiple tracked stars can be marked in an image frame with default values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(30, 35), (40, 40), (45, 35)]
+
+ image_frame.mark(
+ tracked_stars={Star(last_positions=[target]) for target in targets},
+ mark_tracked_stars=True,
+ )
+
+ for target in targets:
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_POSITION_DEFAULT_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_tracked_stars_4(self):
+ """Multiple tracked stars can be marked in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(30, 35), (40, 40), (45, 35)]
+ color = (0, 0, 100)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ tracked_stars={Star(last_positions=[target]) for target in targets},
+ mark_tracked_stars=True,
+ mark_position_default_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ for target in targets:
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_tracked_stars_5(self):
+ """Multiple tracked stars can be marked in an image frame with unique colors."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(30, 35), (40, 40), (45, 35)]
+ colors = [(0, 0, 100), (0, 100, 0), (100, 0, 0)]
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ tracked_stars={
+ Star(last_positions=[target], color=list(color))
+ for target, color in zip(targets, colors)
+ },
+ mark_tracked_stars=True,
+ colorized_tracked_stars=True,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ for target, color in zip(targets, colors):
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_1(self):
+ """A shooting star can be marked in an image frame with default values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (35, 35)
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[target])},
+ mark_shooting_stars=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_SHOOTING_STAR_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_2(self):
+ """A shooting star can be marked in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (35, 35)
+ color = (0, 100, 100)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[target])},
+ mark_shooting_stars=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ mark_shooting_star_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_3(self):
+ """
+ Multiple shooting stars can be marked in an image frame with default values.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(35, 35), (40, 40), (45, 45)]
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[target]) for target in targets},
+ mark_shooting_stars=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ )
+
+ for target in targets:
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_SHOOTING_STAR_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_4(self):
+ """
+ Multiple shooting stars can be marked in an image frame with custom values.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ targets = [(35, 35), (40, 40), (45, 45)]
+ color = (0, 100, 100)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[target]) for target in targets},
+ mark_shooting_stars=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ mark_shooting_star_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ for target in targets:
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_5(self):
+ """A shooting star can be marked in an image frame with its movement vector."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (35, 35)
+ end = (40, 40)
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[start, end])},
+ mark_shooting_stars=True,
+ mark_movement_vector=True,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ )
+
+ cv.line(
+ image_data,
+ pt1=start,
+ pt2=end,
+ color=MARK_MOVEMENT_VECTOR_COLOR,
+ thickness=MARK_THICKNESS,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(end[0]),
+ int(end[1]),
+ ),
+ color=MARK_SHOOTING_STAR_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_6(self):
+ """
+ A shooting star can be marked in an image frame with its next expected position.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (35, 35)
+ end = (40, 40)
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[start], next_expected_position=end)},
+ mark_shooting_stars=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=True,
+ mark_last_predicted_position=False,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(start[0]),
+ int(start[1]),
+ ),
+ color=MARK_SHOOTING_STAR_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(end[0]),
+ int(end[1]),
+ ),
+ color=MARK_NEXT_EXPECTED_POSITION_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_shooting_stars_7(self):
+ """
+ A shooting star can be marked in an image frame with its last predicted position.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (35, 35)
+ end = (40, 40)
+
+ image_frame.mark(
+ shooting_stars={Star(last_positions=[start], last_predicted_position=end)},
+ mark_shooting_stars=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=True,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(start[0]),
+ int(start[1]),
+ ),
+ color=MARK_SHOOTING_STAR_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(end[0]),
+ int(end[1]),
+ ),
+ color=MARK_LAST_PREDICTED_POSITION_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_satellite_1(self):
+ """A satellite can be marked in an image frame with default values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (40, 40)
+
+ image_frame.mark(
+ satellite=Star(last_positions=[target]),
+ mark_satellite=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=MARK_SATELLITE_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_satellite_2(self):
+ """A satellite can be marked in an image frame with custom values."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ target = (40, 40)
+ color = (0, 100, 0)
+ radius = 5
+ thickness = 3
+
+ image_frame.mark(
+ satellite=Star(last_positions=[target]),
+ mark_satellite=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ mark_satellite_color=color,
+ mark_radius=radius,
+ mark_thickness=thickness,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(target[0]),
+ int(target[1]),
+ ),
+ color=color,
+ radius=radius,
+ thickness=thickness,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_satellite_3(self):
+ """A satellite can be marked in an image frame with its movement vector."""
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (40, 40)
+ end = (45, 45)
+
+ image_frame.mark(
+ satellite=Star(last_positions=[start, end]),
+ mark_satellite=True,
+ mark_movement_vector=True,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=False,
+ )
+
+ cv.line(
+ image_data,
+ pt1=start,
+ pt2=end,
+ color=MARK_MOVEMENT_VECTOR_COLOR,
+ thickness=MARK_THICKNESS,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(end[0]),
+ int(end[1]),
+ ),
+ color=MARK_SATELLITE_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_satellite_4(self):
+ """
+ A satellite can be marked in an image frame with its next expected position.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (40, 40)
+ end = (45, 45)
+
+ image_frame.mark(
+ satellite=Star(last_positions=[start], next_expected_position=end),
+ mark_satellite=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=True,
+ mark_last_predicted_position=False,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(start[0]),
+ int(start[1]),
+ ),
+ color=MARK_SATELLITE_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(end[0]),
+ int(end[1]),
+ ),
+ color=MARK_NEXT_EXPECTED_POSITION_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ def test_mark_satellite_5(self):
+ """
+ A satellite can be marked in an image frame with its last predicted position.
+ """
+
+ image_data = np.zeros((50, 50, 3), dtype=np.uint8)
+ image_frame = ImageFrame(image_data)
+
+ start = (40, 40)
+ end = (45, 45)
+
+ image_frame.mark(
+ satellite=Star(last_positions=[start], last_predicted_position=end),
+ mark_satellite=True,
+ mark_movement_vector=False,
+ mark_next_expected_position=False,
+ mark_last_predicted_position=True,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(start[0]),
+ int(start[1]),
+ ),
+ color=MARK_SATELLITE_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ cv.circle(
+ image_data,
+ center=(
+ int(end[0]),
+ int(end[1]),
+ ),
+ color=MARK_LAST_PREDICTED_POSITION_COLOR,
+ radius=MARK_RADIUS,
+ thickness=MARK_THICKNESS,
+ )
+
+ self.assertTrue(np.array_equal(image_data, image_frame.data))
+
+ # ToDo: Implement unit tests for the 'tracking_phase_video_simulation' method.
diff --git a/test/test_image_processor.py b/test/test_image_processor.py
index bf141a2..61ec33b 100755
--- a/test/test_image_processor.py
+++ b/test/test_image_processor.py
@@ -13,9 +13,10 @@
import cv2 as cv
+from src.image_frame import ImageFrame
from src.image_processor import (
detect_stars,
- prune_close_points,
+ _prune_close_points,
track_stars,
detect_shooting_stars,
detect_blinking_star,
@@ -24,7 +25,7 @@
class ImageProcessorTestCase(unittest.TestCase):
- """Class to test the image_processor script."""
+ """Class to test the image_processor script's functions."""
@classmethod
def setUpClass(cls):
@@ -33,7 +34,7 @@ def setUpClass(cls):
def test_detect_stars_1(self):
"""detect_stars can detect one star."""
- image = cv.imread(str(Path("./data/images/stellarium-007.png")))
+ image = ImageFrame(cv.imread(str(Path("./data/images/stellarium-007.png"))))
if image is None:
sys.exit("Could not read the image.")
@@ -46,7 +47,7 @@ def test_detect_stars_1(self):
def test_detect_stars_2(self):
"""detect_stars can detect multiple stars."""
- image = cv.imread(str(Path("./data/images/stellarium-003.png")))
+ image = ImageFrame(cv.imread(str(Path("./data/images/stellarium-003.png"))))
if image is None:
sys.exit("Could not read the image.")
@@ -73,7 +74,7 @@ def test_prune_close_points_1(self):
]
expected_result = [(10, 10)]
- result = prune_close_points(star_positions, min_prune_distance=5)
+ result = _prune_close_points(star_positions, min_prune_distance=5)
self.assertEqual(expected_result, result)
def test_prune_close_points_2(self):
@@ -89,7 +90,7 @@ def test_prune_close_points_2(self):
(15, 15),
]
- result = prune_close_points(star_positions, min_prune_distance=5)
+ result = _prune_close_points(star_positions, min_prune_distance=5)
self.assertEqual(expected_result, result)
def test_track_stars_0(self):
@@ -175,6 +176,7 @@ def test_track_stars_2(self):
detection_confidence=1,
movement_vector=(0, 0),
color=[],
+ last_predicted_position=(10, 15),
)
}
diff --git a/test/test_input_stream.py b/test/test_input_stream.py
new file mode 100644
index 0000000..61d09e1
--- /dev/null
+++ b/test/test_input_stream.py
@@ -0,0 +1,23 @@
+#! /usr/bin/env python3
+# -*- coding: utf-8 -*-
+"""
+This program tests the correct functionality of the functions at src/input_stream.py
+ file.
+"""
+
+
+import unittest
+
+from src.input_stream import InputStream
+
+
+class InputStreamClassTestCase(unittest.TestCase):
+ """Class to test the InputStream class and its methods."""
+
+ def test_1(self):
+ """..."""
+
+ # input_stream = InputStream()
+
+
+# ToDo: Add unit tests
diff --git a/test/test_star.py b/test/test_star.py
index e71f203..0e22d3b 100755
--- a/test/test_star.py
+++ b/test/test_star.py
@@ -1,8 +1,7 @@
#! /usr/bin/env python3
# -*- coding: utf-8 -*-
"""
-This program tests the correct functionality of the functions at src/image_processor.py
- file.
+This program tests the correct functionality of the functions at src/star.py file.
"""
import random
@@ -17,12 +16,12 @@
DEFAULT_VECTOR,
Star,
id_generator,
- get_mean_vector,
+ get_average_vector,
)
class StarClassTestCase(unittest.TestCase):
- """Class to test the image_processor script."""
+ """Class to test the Star class and its methods."""
@classmethod
def setUpClass(cls):
@@ -58,7 +57,8 @@ def test_default_star(self):
"color": [255, 0, 0],
"frames_since_last_detection": 0,
"last_detected_position": None,
- "expected_position": None,
+ "next_expected_position": None,
+ "last_predicted_position": None,
}
result = Star()
@@ -83,7 +83,8 @@ def test_custom_star(self):
"color": [0, 0, 100],
"frames_since_last_detection": 1,
"last_detected_position": (10, 15),
- "expected_position": (10, 15),
+ "next_expected_position": (10, 15),
+ "last_predicted_position": (10, 15),
}
result = Star(
@@ -150,9 +151,38 @@ def test_eq_2(self):
self.assertNotEqual(star_1, star_2)
+ def test_repr(self):
+ """__repr__ can return the string representation of a star."""
+
+ star = Star()
+ expected_result = (
+ f"<{star.__class__.__module__}.{star.__class__.__name__}"
+ + f" object at {hex(id(star))}>: "
+ + str(
+ {
+ "id": 0,
+ "last_positions": [],
+ "last_times_detected": [],
+ "lifetime": 1,
+ "left_lifetime": DEFAULT_LEFT_LIFETIME,
+ "blinking_freq": VIDEO_FPS,
+ "detection_confidence": 0,
+ "movement_vector": DEFAULT_VECTOR,
+ "color": [255, 0.0, 0.0],
+ "frames_since_last_detection": 0,
+ "last_detected_position": None,
+ "next_expected_position": None,
+ "last_predicted_position": None,
+ }
+ )
+ )
+ self.assertEqual(expected_result, star.__repr__())
+
def test_update_info_1(self):
- """update_info can add the new star position and update the star information
- accordingly."""
+ """
+ update_info can add the new star position and update the star information
+ accordingly.
+ """
random.random = Mock(return_value=1)
Star._id = MagicMock()
@@ -182,6 +212,7 @@ def test_update_info_1(self):
blinking_freq=video_fps,
detection_confidence=-1,
movement_vector=(1, 1),
+ last_predicted_position=(10, 15),
)
}
@@ -200,8 +231,10 @@ def test_update_info_1(self):
self.assertEqual(expected_stars, detected_stars)
def test_update_info_2(self):
- """update_info can reduce the lifetime of the star if it has no new position and
- update its information accordingly."""
+ """
+ update_info can reduce the lifetime of the star if it has no new position and
+ update its information accordingly.
+ """
random.random = Mock(return_value=1)
Star._id = MagicMock()
@@ -251,8 +284,10 @@ def test_update_info_3(self):
self.assertEqual(expected_stars, detected_stars)
def test_get_new_star_position_1(self):
- """get_new_star_position can get the new position if it coincides with the
- expected one."""
+ """
+ get_new_star_position can get the new position if it coincides with the expected
+ one.
+ """
star_positions = [
(5, 5),
@@ -269,8 +304,9 @@ def test_get_new_star_position_1(self):
self.assertEqual(expected_result, result)
def test_get_new_star_position_2(self):
- """get_new_star_position can get the closest new position to the expected
- one."""
+ """
+ get_new_star_position can get the closest new position to the expected one.
+ """
star_positions = [
(5, 5),
@@ -287,8 +323,9 @@ def test_get_new_star_position_2(self):
self.assertEqual(expected_result, result)
def test_get_new_star_position_3(self):
- """get_new_star_position can't get any new position if there are no stars in
- range."""
+ """
+ get_new_star_position can't get any new position if there are no stars in range.
+ """
star_positions = [
(5, 5),
@@ -305,8 +342,9 @@ def test_get_new_star_position_3(self):
self.assertEqual(expected_result, result)
def test_get_new_star_position_4(self):
- """get_new_star_position can't get any new position if there are no new
- stars."""
+ """
+ get_new_star_position can't get any new position if there are no new stars.
+ """
star_positions = []
star = Star(
@@ -319,8 +357,10 @@ def test_get_new_star_position_4(self):
self.assertEqual(expected_result, result)
def test_get_new_movement_vector_1(self):
- """get_new_movement_vector can return a default movement vector if not enough
- points are given."""
+ """
+ get_new_movement_vector can return a default movement vector if not enough
+ points are given.
+ """
star = Star(last_positions=[])
expected_result = (0, 0)
@@ -329,8 +369,9 @@ def test_get_new_movement_vector_1(self):
self.assertEqual(expected_result, result)
def test_get_new_movement_vector_2(self):
- """get_new_movement_vector can get the movement vector from a list of
- positions."""
+ """
+ get_new_movement_vector can get the movement vector from a list of positions.
+ """
star = Star(
last_positions=[
@@ -344,13 +385,17 @@ def test_get_new_movement_vector_2(self):
expected_result = (1, 0)
result = star.get_new_movement_vector(
- min_history_length=1, remove_outliers=False
+ min_history_length=1,
+ remove_outliers=False,
+ movement_vector_computation_method="mean",
)
self.assertEqual(expected_result, result)
def test_get_new_movement_vector_3(self):
- """get_new_movement_vector can remove an outlier point and get the movement
- vector of the remaining positions."""
+ """
+ get_new_movement_vector can remove an outlier point and get the movement vector
+ of the remaining positions.
+ """
star = Star(
last_positions=[
@@ -367,12 +412,15 @@ def test_get_new_movement_vector_3(self):
min_history_length=1,
max_outlier_threshold=1.5,
remove_outliers=True,
+ movement_vector_computation_method="mean",
)
self.assertEqual(expected_result, result)
def test_get_new_movement_vector_4(self):
- """get_new_movement_vector can return a default movement vector if all positions
- are treated as outliers."""
+ """
+ get_new_movement_vector can return a default movement vector if all positions
+ are treated as outliers.
+ """
star = Star(
last_positions=[
@@ -390,12 +438,14 @@ def test_get_new_movement_vector_4(self):
max_outlier_threshold=0.1,
remove_outliers=True,
default_vector=(0, 0),
+ movement_vector_computation_method="mean",
)
self.assertEqual(expected_result, result)
def test_get_new_movement_vector_5(self):
- """get_new_movement_vector can get the movement vector even with lost
- positions."""
+ """
+ get_new_movement_vector can get the movement vector even with lost positions.
+ """
star = Star(
last_positions=[
@@ -413,13 +463,17 @@ def test_get_new_movement_vector_5(self):
expected_result = (1, 0)
result = star.get_new_movement_vector(
- min_history_length=1, remove_outliers=False
+ min_history_length=1,
+ remove_outliers=False,
+ movement_vector_computation_method="mean",
)
self.assertEqual(expected_result, result)
def test_get_individual_movement_vectors_1(self):
- """get_individual_movement_vectors can get the individual movement vectors from
- two detected positions."""
+ """
+ get_individual_movement_vectors can get the individual movement vectors from two
+ detected positions.
+ """
star = Star(
last_positions=[
@@ -433,8 +487,10 @@ def test_get_individual_movement_vectors_1(self):
self.assertEqual(expected_result, result)
def test_get_individual_movement_vectors_2(self):
- """get_individual_movement_vectors can get the individual movement vectors with
- one undetected position in between."""
+ """
+ get_individual_movement_vectors can get the individual movement vectors with one
+ undetected position in between.
+ """
star = Star(
last_positions=[
@@ -449,8 +505,10 @@ def test_get_individual_movement_vectors_2(self):
self.assertEqual(expected_result, result)
def test_get_individual_movement_vectors_3(self):
- """get_individual_movement_vectors can return an empty list if there are not
- enough detected positions."""
+ """
+ get_individual_movement_vectors can return an empty list if there are not enough
+ detected positions.
+ """
star = Star(
last_positions=[
@@ -463,8 +521,10 @@ def test_get_individual_movement_vectors_3(self):
self.assertEqual(expected_result, result)
def test_get_individual_movement_vectors_4(self):
- """get_individual_movement_vectors can return an empty list if there are not
- enough detected positions."""
+ """
+ get_individual_movement_vectors can return an empty list if there are not enough
+ detected positions.
+ """
star = Star(
last_positions=[
@@ -477,8 +537,10 @@ def test_get_individual_movement_vectors_4(self):
self.assertEqual(expected_result, result)
def test_get_individual_movement_vectors_5(self):
- """get_individual_movement_vectors can return an empty list if there are not
- enough detected positions."""
+ """
+ get_individual_movement_vectors can return an empty list if there are not enough
+ detected positions.
+ """
star = Star(
last_positions=[
@@ -493,8 +555,8 @@ def test_get_individual_movement_vectors_5(self):
result = star.get_individual_movement_vectors()
self.assertEqual(expected_result, result)
- def test_expected_position_1(self):
- """expected_position can return the expected position of a static star."""
+ def test_next_expected_position_1(self):
+ """next_expected_position can return the expected position of a static star."""
star = Star(
movement_vector=(0, 0),
@@ -503,10 +565,10 @@ def test_expected_position_1(self):
)
expected_result = (10, 15)
- self.assertEqual(expected_result, star.expected_position)
+ self.assertEqual(expected_result, star.next_expected_position)
- def test_expected_position_2(self):
- """expected_position can return the expected position of a moving star."""
+ def test_next_expected_position_2(self):
+ """next_expected_position can return the expected position of a moving star."""
star = Star(
movement_vector=(1, 1),
@@ -515,10 +577,12 @@ def test_expected_position_2(self):
)
expected_result = (11, 16)
- self.assertEqual(expected_result, star.expected_position)
+ self.assertEqual(expected_result, star.next_expected_position)
- def test_expected_position_3(self):
- """expected_position can return the expected position of a lost moving star."""
+ def test_next_expected_position_3(self):
+ """
+ next_expected_position can return the expected position of a lost moving star.
+ """
star = Star(
movement_vector=(1, 1),
@@ -527,10 +591,38 @@ def test_expected_position_3(self):
)
expected_result = (13, 18)
- self.assertEqual(expected_result, star.expected_position)
+ self.assertEqual(expected_result, star.next_expected_position)
+
+ def test_last_predicted_position_1(self):
+ """
+ last_predicted_position can return the last predicted position of a static star.
+ """
+
+ star = Star(
+ last_positions=[(10, 15)],
+ movement_vector=(0, 0),
+ )
+ expected_result = (10, 15)
+
+ self.assertEqual(expected_result, star.last_predicted_position)
+
+ def test_last_predicted_position_2(self):
+ """
+ last_predicted_position can return the last predicted position of a moving star.
+ """
+
+ star = Star(
+ last_positions=[(10, 15)],
+ movement_vector=(1, 1),
+ )
+ expected_result = (11, 16)
+
+ self.assertEqual(expected_result, star.last_predicted_position)
def test_last_detected_position_1(self):
- """last_detected_position can return the last detected position of the star."""
+ """
+ last_detected_position can return the last detected position of the star.
+ """
star = Star(
last_positions=[(10, 15)],
@@ -540,8 +632,10 @@ def test_last_detected_position_1(self):
self.assertEqual(expected_result, star.last_detected_position)
def test_last_detected_position_2(self):
- """last_detected_position can return the last detected position of the star
- ignoring the not detected ones."""
+ """
+ last_detected_position can return the last detected position of the star
+ ignoring the not detected ones.
+ """
star = Star(
last_positions=[(10, 15), None, None],
@@ -561,8 +655,9 @@ def test_last_detected_position_3(self):
self.assertEqual(expected_result, star.last_detected_position)
def test_last_detected_position_4(self):
- """last_detected_position can return None if the star has no detected
- positions."""
+ """
+ last_detected_position can return None if the star has no detected positions.
+ """
star = Star(
last_positions=[None, None, None],
@@ -571,30 +666,102 @@ def test_last_detected_position_4(self):
self.assertEqual(expected_result, star.last_detected_position)
- def test_get_mean_vect_1(self):
- """get_mean_vect can return a default vector if not enough vectors are given."""
+ def test_get_average_vect_1(self):
+ """get_average_vect can return the default vector if an empty list is given."""
vectors = []
expected_result = (0, 0)
- result = get_mean_vector(vectors, default_vector=(0, 0))
+ result = get_average_vector(vectors, default_vector=(0, 0))
self.assertEqual(expected_result, result)
- def test_get_mean_vect_2(self):
- """get_mean_vect can get the mean vector from a list of vectors."""
+ def test_get_average_vect_2(self):
+ """get_average_vect can get the mean vector from a list of vectors."""
vectors = [
- (1, 4),
- (2, 4),
- (3, 4),
- (4, 4),
- (5, 4),
+ (3.2, 7.1),
+ (2.1, 5.9),
+ (1.8, 6.2),
+ (2.0, 5.8),
+ (1.8, 6.5),
+ (2.3, 6.8),
+ (2.5, 5.9),
]
- expected_result = (3, 4)
+ expected_result = (2.24, 6.31)
- result = get_mean_vector(vectors, default_vector=(0, 0))
+ result = get_average_vector(vectors, computation_method="mean")
+ self.assertAlmostEqual(expected_result[0], result[0], places=2)
+
+ def test_get_average_vect_3(self):
+ """
+ get_average_vect can get the median vector from a list of vectors containing an
+ odd number of items.
+ """
+
+ vectors = [
+ (3.2, 7.1),
+ (2.1, 5.9),
+ (1.8, 6.2),
+ (2.0, 5.8),
+ (1.8, 6.5),
+ (2.3, 6.8),
+ (2.5, 5.9),
+ ]
+ expected_result = (2.1, 6.2)
+
+ result = get_average_vector(vectors, computation_method="median")
+ self.assertEqual(expected_result, result)
+
+ def test_get_average_vect_4(self):
+ """
+ get_average_vect can get the median vector from a list of vectors containing an
+ even number of items.
+ """
+
+ vectors = [
+ (3.2, 7.1),
+ (2.1, 5.9),
+ (1.8, 6.2),
+ (2.0, 5.8),
+ (1.8, 6.5),
+ (2.3, 6.8),
+ (2.5, 5.9),
+ (2.9, 6.3),
+ ]
+ expected_result = (2.2, 6.25)
+
+ result = get_average_vector(vectors, computation_method="median")
+ self.assertEqual(expected_result, result)
+
+ def test_get_average_vect_5(self):
+ """get_average_vect can get the mode vector from a list of vectors."""
+
+ vectors = [
+ (3.2, 7.1),
+ (2.1, 5.9),
+ (1.8, 6.2),
+ (2.0, 5.8),
+ (1.8, 6.5),
+ (2.3, 6.8),
+ (2.5, 5.9),
+ (2.9, 6.3),
+ ]
+ expected_result = (1.8, 5.9)
+
+ result = get_average_vector(vectors, computation_method="mode")
self.assertEqual(expected_result, result)
+ def test_get_average_vect_6(self):
+ """
+ get_average_vect can raise an exception if an invalid computation method is
+ given.
+ """
+
+ vectors = [(1, 2), (3, 4)]
+
+ with self.assertRaises(ValueError):
+ get_average_vector(vectors, computation_method="~invalid~")
+
if __name__ == "__main__":
unittest.main()