From 34b7fde2d4299ac99f7bb5b9bbe37cb5bfa827c0 Mon Sep 17 00:00:00 2001 From: "Benguria Elguezabal, Gorka" <gorka.benguria@tecnalia.com> Date: Tue, 16 Jan 2024 01:30:49 +0100 Subject: [PATCH] y3 --- .dockerignore | 113 +- .env.gen | 106 + .envs/global/development | 12 + .envs/global/prod | 8 + .envs/global/release | 11 + .envs/modules/psl/development | 12 + .envs/modules/psl/prod | 8 + .envs/modules/psl/release | 11 + .gitignore | 4 +- .gitlab-ci.yml | 141 +- .openapi-generator/FILES | 20 - .openapi-generator/VERSION | 1 - Dockerfile | 22 +- Dockerfile-alpine | 34 + LICENSE | 201 ++ README.md | 2 +- build/docker-compose.yaml | 7 + build/image/docker-compose.yaml | 3 + build/inline-cache/docker-compose.yaml | 7 + docker-compose-artifactory.yaml | 5 + docker-compose-dev.yaml | 4 + docker-compose-traefik-aliases.yaml | 6 + docker-compose-traefik-network-external.yaml | 4 + docker-compose-traefik-network-internal.yaml | 3 + docker-compose.yaml | 24 + influxdb/dashboards/all_input_metrics.json | 343 ++++ .../dashboards/psl_variable_analysis.json | 470 +++++ influxdb/variables/deployment_id.json | 35 + influxdb/variables/variable.json | 43 + openapi.yaml | 16 +- piacere-build/docker-compose.yaml | 7 + psl/test/test_self_learning_flow.py | 9 + release/docker-compose.yaml | 3 + requirements.txt | 61 +- setup.py | 7 +- src/psl/adapters/csv_to_metric_source.py | 5 +- src/psl/adapters/influxdb_to_influxdb.py | 118 +- src/psl/adapters/influxdb_to_metric_source.py | 250 ++- src/psl/adapters/predictor_to_predictor.py | 75 +- src/psl/adapters/sh_client_to_sh_client.py | 5 +- src/psl/adapters/tmp.py | 98 - src/psl/config.yaml | 79 +- .../controllers/self_learning_controller.py | 11 +- src/psl/flows/self_learning_flow.py | 81 +- src/psl/models/__init__.py | 1 + src/psl/models/deployment.py | 66 + src/psl/openapi/openapi.yaml | 10 +- src/psl/predictor/predictor.py | 1527 ++++++++++++--- src/psl/predictor/predictor_config.txt | 72 +- src/psl/predictor/predictor_utils.py | 340 +++- src/psl/services/self_learning_service.py | 7 +- test_input_data/psl_data.csv | 1729 +++++++++++++++++ test_input_data/usage_idle_data.csv | 2 +- tox.ini | 2 +- 54 files changed, 5428 insertions(+), 813 deletions(-) create mode 100644 .env.gen create mode 100644 .envs/global/development create mode 100644 .envs/global/prod create mode 100644 .envs/global/release create mode 100644 .envs/modules/psl/development create mode 100644 .envs/modules/psl/prod create mode 100644 .envs/modules/psl/release delete mode 100644 .openapi-generator/FILES delete mode 100644 .openapi-generator/VERSION create mode 100644 Dockerfile-alpine create mode 100644 LICENSE create mode 100644 build/docker-compose.yaml create mode 100644 build/image/docker-compose.yaml create mode 100644 build/inline-cache/docker-compose.yaml create mode 100644 docker-compose-artifactory.yaml create mode 100644 docker-compose-dev.yaml create mode 100644 docker-compose-traefik-aliases.yaml create mode 100644 docker-compose-traefik-network-external.yaml create mode 100644 docker-compose-traefik-network-internal.yaml create mode 100644 docker-compose.yaml create mode 100644 influxdb/dashboards/all_input_metrics.json create mode 100644 influxdb/dashboards/psl_variable_analysis.json create mode 100644 influxdb/variables/deployment_id.json create mode 100644 influxdb/variables/variable.json create mode 100644 piacere-build/docker-compose.yaml create mode 100644 psl/test/test_self_learning_flow.py create mode 100644 release/docker-compose.yaml delete mode 100644 src/psl/adapters/tmp.py create mode 100644 src/psl/models/deployment.py create mode 100644 test_input_data/psl_data.csv diff --git a/.dockerignore b/.dockerignore index 1356e64..f961960 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,11 +1,10 @@ -# temporal for refactor -/src.*/ -# development ignore -/config.yaml -/predictor_config.txt -/data/ -/data/models/ -/.vscode/ +.travis.yaml +.openapi-generator-ignore +README.md +tox.ini +git_push.sh +test-requirements.txt +setup.py # Byte-compiled / optimized / DLL files __pycache__/ @@ -17,6 +16,7 @@ __pycache__/ # Distribution / packaging .Python +env/ build/ develop-eggs/ dist/ @@ -28,12 +28,9 @@ lib64/ parts/ sdist/ var/ -wheels/ -share/python-wheels/ *.egg-info/ .installed.cfg *.egg -MANIFEST # PyInstaller # Usually these files are written by a python script from a template @@ -48,17 +45,15 @@ pip-delete-this-directory.txt # Unit test / coverage reports htmlcov/ .tox/ -.nox/ .coverage .coverage.* .cache nosetests.xml coverage.xml -*.cover -*.py,cover +*,cover .hypothesis/ -.pytest_cache/ -cover/ +venv/ +.python-version # Translations *.mo @@ -66,96 +61,12 @@ cover/ # Django stuff: *.log -local_settings.py -db.sqlite3 -db.sqlite3-journal - -# Flask stuff: -instance/ -.webassets-cache - -# Scrapy stuff: -.scrapy # Sphinx documentation docs/_build/ # PyBuilder -.pybuilder/ target/ -# Jupyter Notebook +#Ipython Notebook .ipynb_checkpoints - -# IPython -profile_default/ -ipython_config.py - -# pyenv -# For a library or package, you might want to ignore these files since the code is -# intended to run in multiple environments; otherwise, check them in: -# .python-version - -# pipenv -# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. -# However, in case of collaboration, if having platform-specific dependencies or dependencies -# having no cross-platform support, pipenv may install dependencies that don't work, or not -# install all needed dependencies. -#Pipfile.lock - -# poetry -# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control. -# This is especially recommended for binary packages to ensure reproducibility, and is more -# commonly ignored for libraries. -# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control -#poetry.lock - -# PEP 582; used by e.g. github.com/David-OConnor/pyflow -__pypackages__/ - -# Celery stuff -celerybeat-schedule -celerybeat.pid - -# SageMath parsed files -*.sage.py - -# Environments -.env -.venv -env/ -venv/ -ENV/ -env.bak/ -venv.bak/ - -# Spyder project settings -.spyderproject -.spyproject - -# Rope project settings -.ropeproject - -# mkdocs documentation -/site - -# mypy -.mypy_cache/ -.dmypy.json -dmypy.json - -# Pyre type checker -.pyre/ - -# pytype static type analyzer -.pytype/ - -# Cython debug symbols -cython_debug/ - -# PyCharm -# JetBrains specific template is maintainted in a separate JetBrains.gitignore that can -# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore -# and can be added to the global gitignore or merged into this file. For a more nuclear -# option (not recommended) you can uncomment the following to ignore the entire idea folder. -#.idea/ \ No newline at end of file diff --git a/.env.gen b/.env.gen new file mode 100644 index 0000000..e4d0095 --- /dev/null +++ b/.env.gen @@ -0,0 +1,106 @@ +# Reference documentation https://docs.docker.com/compose/environment-variables/ +# Focus default variables as production, to allow direct download and run in production +# Required external variables that must be defined externally are those that have no value + +#### Environments managed #### +# this is the default environment if needed uncomment and adjust +# some conventions on environment prefixes +# - development: purpouse is to cache build and start the setup locally using cache images exposing dev ports (i.e 3306, 5432, 8086, ...) for debug and development purposes. It is the default behaviour (local:run-build-cache) +# - release: purpouse is to generate images (that do not use BUILDKIT_INLINE_CACHE 1) tagged for the clients/pilots usage (release:run-build-release) +# - prod: purpose is to generate non building docker-compose that uses the release to deploy on generic client (prod:run-release) +# - test: the purpouse is to test from the cache images the correct behaviour without exposing ports (test:run-cache) +# types of building +# - run-build-cache: it focuses in the generation of images with BUILDKIT_INLINE_CACHE 1 for its usage in the cache-from for subsequent build, for each compose-file in compose-file build it finds build/cache the same name to add it to the build, it will use cache from. +# - run-build-release: it focuses in the generation of images for distribution it avoid using BUILDKIT_INLINE_CACHE 1 to reduce the size, it will use cache from. +# - build-cache: it focuses in the generation of images with BUILDKIT_INLINE_CACHE 1 for its usage in the cache-from for subsequent build, for each compose-file in compose-file build it finds build/cache the same name to add it to the build, it will use cache from. +# - build-release: it focuses in the generation of images for distribution it avoid using BUILDKIT_INLINE_CACHE 1 to reduce the size, it will not use cache from. +# - run-cache: it runs using cache images +# - run-release: it runs using release images +# default enviroment +# __ENVIRONMENTS=development:run-build-cache +# to add more enviroments use split with ";" +__ENVIRONMENTS=development:run-build-cache;prod:run-release;release:build-release + +#### Modules managed #### +# this will create individual docker composes that enables the individual usage of the modules through the docker-compose command and specific env files i.e. +# __MODULES=traefik;step-ca +# will enable the following docker-compose commands +# docker-compose --env-file .env/modules/traefik/prod ----project-directory . up -d +# __MODULES=traefik;step-ca +__MODULES=psl + +#### default environment #### +# __DEFAULT_ENVIRONMENT=.envs/global/prod + +#### default environment #### +# __DEFAULT_DEVELOPMENT_ENVIRONMENT=.envs/global/development + +#### default release environment #### +# __DEFAULT_RELEASE_ENVIRONMENT=.envs/global/release + +#### Common image related #### +DOCKER_REGISTRY_CACHE_PREFIX=cache.euve.digital.tecnalia.dev:5000 +DOCKER_REGISTRY_CACHE_VERSION=latest + +#### Common Build related #### +# DOCKER_BUILDKIT and COMPOSE_DOCKER_CLI_BUILD do not have effect here, we leave them as documentation +# DOCKER_BUILDKIT=1 +# COMPOSE_DOCKER_CLI_BUILD=1 + +### Common Traefik related ### +TRAEFIK_NETWORK_NAME=traefik_network +TRAEFIK_HTTPS_ENTRYPOINT_NAME=websecure +# TRAEFIK_HTTP_ENTRYPOINT_NAME=web + +#### Common Production related #### +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +# to calculate password hash `openssl passwd -apr1 $ADMIN_PASSWORD` +# ADMIN_PASSWORD_HASH='$apr1$chTuJ7f9$.Ul8E16QYHtydKw.ehzZC.' +# to calculate password bcrypt hash `sudo apt-get update; sudo apt-get install -y apache2-utils; htpasswd -bnBC 12 "" $ADMIN_PASSWORD | tr -d ':\n'` +# ADMIN_PASSWORD_BCRYPT_HASH='$2y$12$NxJ.FkLgDZWWjc15y9bhX./GOTp67krCxWPanJLyCjofKyIN.zS96' +# HTTPS_PORT must be 443 if you use step-ca +HTTPS_PORT=443 +# server host is configured during the sync based on _ENV_LOCAL_ and _ENV_DEPLOY, _ENV_LOCAL_ will be used for test and release unless _ENV_RELEASE_ or _ENV_TEST_ specified +# SERVER_HOST=project.org +SERVER_HOST=ci.piacere.digital.tecnalia.dev + +#### Platform Specific #### +TZ=Madrid +INFLUXD_ORG=piacere + +#### Common docker-compose related #### +# https://docs.docker.com/compose/reference/envvars/#compose_file#compose_project_name +# these are docker-compose related environment variables +COMPOSE_PROJECT_NAME=psl +# _ENV_LOCAL_COMPOSE_FILE_BASE= # These are oriented for local vagrant usually it contains local traefik configuration, dev services, etc +# _ENV_RELEASE_COMPOSE_FILE_BASE= # These are oriented for tagging relevant images for upload to official release repositories +# _ENV_DEPLOY_COMPOSE_FILE_BASE= # These are oriented for final deployment it contains production traefik configuration, etc +# _ENV_TEST_COMPOSE_FILE_BASE= # These are oriented for testing +# COMPOSE_FILE_BASE= # (MANDATORY) These are those main services of the project, that will apply to all the scenarios + +COMPOSE_FILE_BASE= + +COMPOSE_FILE= +# COMPOSE_FILE Is generated automatically + +__psl__COMPOSE_FILE_BASE=docker-compose.yaml +__psl__COMPOSE_FILE_BASE_NETWORK=docker-compose-traefik-network-external.yaml + +__psl__PSL_BASE_PATH= + +__psl_development__SERVER_HOST=192.168.56.1.nip.io + +__psl__IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +__psl__IMAGE_PSL_CACHE=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 + +__psl_development__COMPOSE_FILE_BASE_DEV=docker-compose-dev.yaml + +__psl_release__COMPOSE_FILE_BASE_PIACERE_BUILD=piacere-build/docker-compose.yaml +__psl_release__COMPOSE_FILE_BASE_PIACERE_RELEASE=release/docker-compose.yaml +__psl_release__COMPOSE_FILE_BASE_ARTIFACTORY=docker-compose-artifactory.yaml +__psl_release__COMPOSE_FILE_BASE_TRAEFIK_NETWORK=docker-compose-traefik-network-internal.yaml + + + + diff --git a/.envs/global/development b/.envs/global/development new file mode 100644 index 0000000..5bd7694 --- /dev/null +++ b/.envs/global/development @@ -0,0 +1,12 @@ +DOCKER_REGISTRY_CACHE_PREFIX=cache.euve.digital.tecnalia.dev:5000 +DOCKER_REGISTRY_CACHE_VERSION=latest +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +HTTPS_PORT=443 +SERVER_HOST=192.168.56.1.nip.io +INFLUXD_ORG=piacere +COMPOSE_PROJECT_NAME=psl +PSL_BASE_PATH= +IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +IMAGE_PSL_CACHE=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +COMPOSE_FILE=docker-compose.yaml:docker-compose-traefik-network-external.yaml:docker-compose-dev.yaml:build/docker-compose.yaml:build/inline-cache/docker-compose.yaml:build/image/docker-compose.yaml diff --git a/.envs/global/prod b/.envs/global/prod new file mode 100644 index 0000000..8f2f40c --- /dev/null +++ b/.envs/global/prod @@ -0,0 +1,8 @@ +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +HTTPS_PORT=443 +SERVER_HOST=ci.piacere.digital.tecnalia.dev +INFLUXD_ORG=piacere +COMPOSE_PROJECT_NAME=psl +IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +COMPOSE_FILE=docker-compose.yaml:docker-compose-traefik-network-external.yaml:release/docker-compose.yaml diff --git a/.envs/global/release b/.envs/global/release new file mode 100644 index 0000000..d4ed63e --- /dev/null +++ b/.envs/global/release @@ -0,0 +1,11 @@ +TRAEFIK_NETWORK_NAME=traefik_network +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +HTTPS_PORT=443 +SERVER_HOST=ci.piacere.digital.tecnalia.dev +INFLUXD_ORG=piacere +COMPOSE_PROJECT_NAME=psl +PSL_BASE_PATH= +IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +IMAGE_PSL_CACHE=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +COMPOSE_FILE=docker-compose.yaml:docker-compose-traefik-network-external.yaml:piacere-build/docker-compose.yaml:release/docker-compose.yaml:docker-compose-artifactory.yaml:docker-compose-traefik-network-internal.yaml:build/docker-compose.yaml diff --git a/.envs/modules/psl/development b/.envs/modules/psl/development new file mode 100644 index 0000000..5bd7694 --- /dev/null +++ b/.envs/modules/psl/development @@ -0,0 +1,12 @@ +DOCKER_REGISTRY_CACHE_PREFIX=cache.euve.digital.tecnalia.dev:5000 +DOCKER_REGISTRY_CACHE_VERSION=latest +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +HTTPS_PORT=443 +SERVER_HOST=192.168.56.1.nip.io +INFLUXD_ORG=piacere +COMPOSE_PROJECT_NAME=psl +PSL_BASE_PATH= +IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +IMAGE_PSL_CACHE=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +COMPOSE_FILE=docker-compose.yaml:docker-compose-traefik-network-external.yaml:docker-compose-dev.yaml:build/docker-compose.yaml:build/inline-cache/docker-compose.yaml:build/image/docker-compose.yaml diff --git a/.envs/modules/psl/prod b/.envs/modules/psl/prod new file mode 100644 index 0000000..8f2f40c --- /dev/null +++ b/.envs/modules/psl/prod @@ -0,0 +1,8 @@ +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +HTTPS_PORT=443 +SERVER_HOST=ci.piacere.digital.tecnalia.dev +INFLUXD_ORG=piacere +COMPOSE_PROJECT_NAME=psl +IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +COMPOSE_FILE=docker-compose.yaml:docker-compose-traefik-network-external.yaml:release/docker-compose.yaml diff --git a/.envs/modules/psl/release b/.envs/modules/psl/release new file mode 100644 index 0000000..d4ed63e --- /dev/null +++ b/.envs/modules/psl/release @@ -0,0 +1,11 @@ +TRAEFIK_NETWORK_NAME=traefik_network +ADMIN_USER=admin +ADMIN_PASSWORD=projectPassword +HTTPS_PORT=443 +SERVER_HOST=ci.piacere.digital.tecnalia.dev +INFLUXD_ORG=piacere +COMPOSE_PROJECT_NAME=psl +PSL_BASE_PATH= +IMAGE_PSL=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +IMAGE_PSL_CACHE=optima-piacere-docker-dev.artifact.tecnalia.com/wp6/psl:y3 +COMPOSE_FILE=docker-compose.yaml:docker-compose-traefik-network-external.yaml:piacere-build/docker-compose.yaml:release/docker-compose.yaml:docker-compose-artifactory.yaml:docker-compose-traefik-network-internal.yaml:build/docker-compose.yaml diff --git a/.gitignore b/.gitignore index 19d53a9..358b090 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,8 @@ /data/models/ /.vscode/ /requirement-stable.txt +# open api ignore +/.openapi-generator/ # Byte-compiled / optimized / DLL files __pycache__/ @@ -18,7 +20,7 @@ __pycache__/ # Distribution / packaging .Python -build/ +# build/ develop-eggs/ dist/ downloads/ diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8ea2a21..87d08ff 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,19 +1,122 @@ -sonarqube-check: - image: - name: sonarsource/sonar-scanner-cli:latest - entrypoint: [""] - variables: - SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache - GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task - cache: - key: "${CI_JOB_NAME}" - paths: - - .sonar/cache - script: - - sonar-scanner - allow_failure: true - only: - - main # or the name of your main branch - tags: - - docker - +include: + - project: piacere/private/t23-ci-setup + ref: main + file: + - gitlab-ci-scripts/utils.gitlab-ci.yml + + # Image tag variables generation job ------------- + # Stage: variable-generation --------------------- + - gitlab-ci-scripts/generate-variables.gitlab-ci.yml + + # Downstream t23-ci-setup pipeline trigger job --- + # Stage: integration-tests-publish-deploy -------- + - gitlab-ci-scripts/trigger-downstream.gitlab-ci.yml + + +variables: + COMPONENT_WP: wp6 + PSL_IMAGE_NAME: psl + + IMAGE_NAMES: "$PSL_IMAGE_NAME" + +stages: + - variable-generation + # - quality + # - unit-tests TODO: Fix tests + - build + # - security + - integration-tests-publish-deploy + +# Quality jobs ---------------------- + +#sonarqube-check: +# TODO fails +# image: +# name: sonarsource/sonar-scanner-cli:latest +# entrypoint: [""] +# stage: quality +# variables: +# SONAR_USER_HOME: "${CI_PROJECT_DIR}/.sonar" # Defines the location of the analysis task cache +# GIT_DEPTH: "0" # Tells git to fetch all the branches of the project, required by the analysis task +# cache: +# key: "${CI_JOB_NAME}" +# paths: +# - .sonar/cache +# script: +# - sonar-scanner +# allow_failure: true +# tags: +# - docker + +# Build jobs ---------------------- + +.build-docker-compose: + # image: docker/compose:1.29.2 # this is too old + image: docker:23.0.1 + stage: build + services: + # - docker:20.10.21-dind # not sure if this is the latest + - docker:dind + variables: + GIT_DEPTH: 1 + GIT_SUBMODULE_STRATEGY: recursive + GIT_SUBMODULE_DEPTH: 1 + DOCKER_BUILDKIT: 1 + COMPOSE_DOCKER_CLI_BUILD: 1 + DOCKER_COMPOSE_PATH: "." + DOCKER_COMPOSE_ENV_FILE_CACHE: ".envs/global/release" + DOCKER_COMPOSE_ENV_FILE: ".envs/global/release" + before_script: + - !reference [.artifactory-login] + script: + - apk add docker-compose + - cd $DOCKER_COMPOSE_PATH + - docker-compose --env-file $DOCKER_COMPOSE_ENV_FILE_CACHE --project-directory ./ pull || true + - docker-compose --env-file $DOCKER_COMPOSE_ENV_FILE_CACHE --project-directory ./ config + - docker-compose --env-file $DOCKER_COMPOSE_ENV_FILE --project-directory ./ build + - docker-compose --env-file $DOCKER_COMPOSE_ENV_FILE --project-directory ./ push + - docker-compose --env-file $DOCKER_COMPOSE_ENV_FILE --project-directory ./ config | grep image + tags: + - docker + +build-temp-docker-compose: + extends: + - .build-docker-compose + variables: + IMAGE_PSL: "$TMP_IMAGE_PSL" + +build-release-docker-compose: + extends: + - .build-docker-compose + when: manual + +# Security job in tests stage------------------------ + +# security-trivy-psl: +# stage: security +# variables: +# TMP_IMAGE: "$TMP_IMAGE_PSL" +# trigger: !reference [.trigger-security-trivy] +# needs: +# - job: build-temp-docker-compose +# - job: generate-variables +# artifacts: true + +# Tests jobs ------------------------ + +# TODO: Tests are failing. There is a problem with imports + +# run-unit-tests: +# image: python:3.9 +# stage: unit-tests +# before_script: +# - pip install tox +# script: +# - tox +# tags: +# - docker + +# Deploy job ------------------------ + +# this is done in stage integration-tests-publish-deploy +# in jobs from t23-ci-setup diff --git a/.openapi-generator/FILES b/.openapi-generator/FILES deleted file mode 100644 index 53f3dac..0000000 --- a/.openapi-generator/FILES +++ /dev/null @@ -1,20 +0,0 @@ -.dockerignore -.travis.yml -README.md -git_push.sh -setup.py -src/psl/__init__.py -src/psl/__main__.py -src/psl/controllers/__init__.py -src/psl/controllers/security_controller_.py -src/psl/controllers/self_learning_controller.py -src/psl/encoder.py -src/psl/models/__init__.py -src/psl/models/base_model_.py -src/psl/models/error.py -src/psl/openapi/openapi.yaml -src/psl/test/__init__.py -src/psl/typing_utils.py -src/psl/util.py -test-requirements.txt -tox.ini diff --git a/.openapi-generator/VERSION b/.openapi-generator/VERSION deleted file mode 100644 index e230c83..0000000 --- a/.openapi-generator/VERSION +++ /dev/null @@ -1 +0,0 @@ -5.3.0 \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 9ddd7c1..0d9c691 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM python:3.9-alpine3.12 +FROM python:3.9-slim-bullseye RUN mkdir -p /usr/src/app WORKDIR /usr/src/app @@ -6,14 +6,18 @@ WORKDIR /usr/src/app COPY requirements.txt /usr/src/app/ RUN \ - apk add --no-cache gcc libffi-dev musl-dev zlib-dev jpeg-dev g++ make cairo-dev openblas-dev lapack-dev qt5-qtbase-dev &&\ - ln -s /usr/lib/qt5/bin/qmake /usr/bin/qmake &&\ - CFLAGS="-g0 -Wl,--strip-all -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib" pip3 install --no-cache-dir --compile --global-option=build_ext -r requirements.txt &&\ - apk del gcc libffi-dev musl-dev zlib-dev jpeg-dev g++ make cairo-dev openblas-dev lapack-dev qt5-qtbase-dev &&\ - rm -rf ~/.cache - -RUN \ - apk add --no-cache openblas libstdc++ libgomp libjpeg libxcb cairo qt5-qtbase +apt-get update -eany \ + && apt-get upgrade -y --no-install-recommends \ + && apt-get install -y --no-install-recommends \ + gcc \ + libcairo2-dev \ +&& pip3 install -r requirements.txt \ + && apt-get remove -y \ + gcc \ + libcairo2-dev \ + && apt-get clean \ + && rm -rf /var/lib/apt/lists/* \ + && rm -rf ~/.cache COPY /src/clients /usr/src/app/clients diff --git a/Dockerfile-alpine b/Dockerfile-alpine new file mode 100644 index 0000000..ba6f7ef --- /dev/null +++ b/Dockerfile-alpine @@ -0,0 +1,34 @@ +FROM python:3.9-alpine3.12 + +RUN mkdir -p /usr/src/app +WORKDIR /usr/src/app + +COPY requirements.txt /usr/src/app/ + +RUN \ + apk add --no-cache gcc libffi-dev musl-dev zlib-dev jpeg-dev g++ make cairo-dev openblas-dev lapack-dev qt5-qtbase-dev &&\ + ln -s /usr/lib/qt5/bin/qmake /usr/bin/qmake &&\ + CFLAGS="-g0 -Wl,--strip-all -I/usr/include:/usr/local/include -L/usr/lib:/usr/local/lib" pip3 install --no-cache-dir --compile --global-option=build_ext -r requirements.txt &&\ + apk del gcc libffi-dev musl-dev zlib-dev jpeg-dev g++ make cairo-dev openblas-dev lapack-dev qt5-qtbase-dev &&\ + rm -rf ~/.cache + +RUN \ + apk add --no-cache openblas libstdc++ libgomp libjpeg libxcb cairo qt5-qtbase + +COPY /src/clients /usr/src/app/clients + +RUN \ + pip3 install --no-cache-dir --compile --global-option=build_ext -e clients/sh_client + +COPY /src/psl /usr/src/app/psl + +EXPOSE 8080 + +ENV PSL__REPOSITORY__FILE=/data/deployments_data \ + PSL__PREDICTOR_ADAPTER__MODELS_PATH=/data/models + +VOLUME /data + +ENTRYPOINT ["python3"] + +CMD ["-m", "psl"] diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..a043ebb --- /dev/null +++ b/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2022 Tecnalia + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/README.md b/README.md index 8ce3d93..8827180 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ Use your favourite IDE, or editing tool. This program requires a conection to influxdb and to self healing therefore you need to provide the conection details in config.yaml or using environment variables i.e. ``` -export PSL__INFLUXDB__CONNECTION__URL=http://pmc-influxdb:8086 +export PSL__INFLUXDB__CONNECTION__URL=http://pm-influxdb:8086 export PSL__SH_CLIENT_ADAPTER__URL=http://sh-gateway:8080/services/shbackend export PSL_INFLUXDB_ORG=piacere export PSL_INFLUXDB_USERNAME=piacere diff --git a/build/docker-compose.yaml b/build/docker-compose.yaml new file mode 100644 index 0000000..cde914a --- /dev/null +++ b/build/docker-compose.yaml @@ -0,0 +1,7 @@ +services: + psl: + build: + context: ${PSL_BASE_PATH}. + dockerfile: Dockerfile + cache_from: + - ${IMAGE_PSL_CACHE:?err} diff --git a/build/image/docker-compose.yaml b/build/image/docker-compose.yaml new file mode 100644 index 0000000..95d0494 --- /dev/null +++ b/build/image/docker-compose.yaml @@ -0,0 +1,3 @@ +services: + psl: + image: ${DOCKER_REGISTRY_CACHE_PREFIX}/piacere/psl:${DOCKER_REGISTRY_CACHE_VERSION:?err} diff --git a/build/inline-cache/docker-compose.yaml b/build/inline-cache/docker-compose.yaml new file mode 100644 index 0000000..012f291 --- /dev/null +++ b/build/inline-cache/docker-compose.yaml @@ -0,0 +1,7 @@ +services: + psl: + build: + cache_from: + - ${DOCKER_REGISTRY_CACHE_PREFIX}/piacere/psl:${DOCKER_REGISTRY_CACHE_VERSION:?err} + args: + BUILDKIT_INLINE_CACHE: 1 # For multistage docker diff --git a/docker-compose-artifactory.yaml b/docker-compose-artifactory.yaml new file mode 100644 index 0000000..5f66061 --- /dev/null +++ b/docker-compose-artifactory.yaml @@ -0,0 +1,5 @@ +services: + psl: + build: + labels: + com.jfrog.artifactory.retention.maxCount: 6 diff --git a/docker-compose-dev.yaml b/docker-compose-dev.yaml new file mode 100644 index 0000000..7f276a0 --- /dev/null +++ b/docker-compose-dev.yaml @@ -0,0 +1,4 @@ +services: + psl: + environment: + PSL__LOGGING__LEVEL: "DEBUG" diff --git a/docker-compose-traefik-aliases.yaml b/docker-compose-traefik-aliases.yaml new file mode 100644 index 0000000..94df84c --- /dev/null +++ b/docker-compose-traefik-aliases.yaml @@ -0,0 +1,6 @@ +services: + traefik: + networks: + traefik_network: + aliases: + - psl.${SERVER_HOST} diff --git a/docker-compose-traefik-network-external.yaml b/docker-compose-traefik-network-external.yaml new file mode 100644 index 0000000..6149618 --- /dev/null +++ b/docker-compose-traefik-network-external.yaml @@ -0,0 +1,4 @@ +networks: + traefik_network: + name: traefik_network + external: true diff --git a/docker-compose-traefik-network-internal.yaml b/docker-compose-traefik-network-internal.yaml new file mode 100644 index 0000000..0d7a2cf --- /dev/null +++ b/docker-compose-traefik-network-internal.yaml @@ -0,0 +1,3 @@ +networks: + traefik_network: + name: ${TRAEFIK_NETWORK_NAME:?err} diff --git a/docker-compose.yaml b/docker-compose.yaml new file mode 100644 index 0000000..04443cc --- /dev/null +++ b/docker-compose.yaml @@ -0,0 +1,24 @@ +services: + psl: + restart: always + environment: + PSL__INFLUXDB__CONNECTION__URL: http://pm-influxdb:8086 # https://influxdb.pm.${SERVER_HOST:?err}:${HTTPS_PORT:?err} + PSL__SH_CLIENT_ADAPTER__URL: http://sh-gateway:8080/services/shbackend #https://sh.${SERVER_HOST:?err}:${HTTPS_PORT:?err}/services/shbackend + PSL__INFLUXDB__CONNECTION__ORG: "${INFLUXD_ORG:?err}" + PSL__INFLUXDB__CONNECTION__USERNAME: "${ADMIN_USER:?err}" + PSL__INFLUXDB__CONNECTION__PASSWORD: "${ADMIN_PASSWORD:?err}" + PSL__INFLUXDB__CONNECTION__TOKEN: "${ADMIN_PASSWORD:?err}" + PSL__INFLUXDB__CONNECTION__SSL: "True" + PSL__INFLUXDB__CONNECTION__VERIFY_SSL: "False" + networks: + traefik_network: + labels: + - "traefik.enable=true" + - "traefik.docker.network=traefik_network" + - "traefik.http.routers.psl.rule=Host(`psl.${SERVER_HOST:?err}`)" + - "traefik.http.routers.psl.entrypoints=websecure" + volumes: + - psl_data:/data + +volumes: + psl_data: diff --git a/influxdb/dashboards/all_input_metrics.json b/influxdb/dashboards/all_input_metrics.json new file mode 100644 index 0000000..f55c9e5 --- /dev/null +++ b/influxdb/dashboards/all_input_metrics.json @@ -0,0 +1,343 @@ +{ + "meta": { + "version": "1", + "type": "dashboard", + "name": "all input metrics-Template", + "description": "template created from dashboard: all input metrics" + }, + "content": { + "data": { + "type": "dashboard", + "attributes": { + "name": "all input metrics", + "description": "" + }, + "relationships": { + "label": { + "data": [] + }, + "cell": { + "data": [ + { + "type": "cell", + "id": "090f20cffae99000" + }, + { + "type": "cell", + "id": "091bf8e4c5e99000" + } + ] + }, + "variable": { + "data": [ + { + "type": "variable", + "id": "091ad8610e70a000" + }, + { + "type": "variable", + "id": "091ad90b9730a000" + } + ] + } + } + }, + "included": [ + { + "id": "090f20cffae99000", + "type": "cell", + "attributes": { + "x": 0, + "y": 0, + "w": 12, + "h": 4 + }, + "relationships": { + "view": { + "data": { + "type": "view", + "id": "090f20cffae99000" + } + } + } + }, + { + "id": "091bf8e4c5e99000", + "type": "cell", + "attributes": { + "x": 0, + "y": 4, + "w": 12, + "h": 4 + }, + "relationships": { + "view": { + "data": { + "type": "view", + "id": "091bf8e4c5e99000" + } + } + } + }, + { + "type": "view", + "id": "090f20cffae99000", + "attributes": { + "name": "\"${v.variable}\"", + "properties": { + "shape": "chronograf-v2", + "queries": [ + { + "text": "import \"strings\"\r\nmeasurement = strings.split(v: v.variable, t: \"_\")[0]\r\nfield = strings.replace(v: v.variable, t: measurement + \"_\", u: \"\", i: 1)\r\nif measurement == \"cpu\" then\r\n from(bucket: \"bucket\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id )\r\n |> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\r\n |> filter(fn: (r) => r[\"_field\"] == field )\r\n |> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\r\n |> map(fn: (r) => ({ r with\r\n _field: r._measurement + \"_\" + r._field\r\n }))\r\n |> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\nelse if measurement == \"disk\" then\r\n from(bucket: \"bucket\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id )\r\n |> filter(fn: (r) => r[\"_measurement\"] == \"disk\" )\r\n |> filter(fn: (r) => r[\"_field\"] == field )\r\n |> filter(fn: (r) => r[\"path\"] == \"/\")\r\n |> map(fn: (r) => ({ r with\r\n _field: r._measurement + \"_\" + r._field\r\n }))\r\n |> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\nelse\r\n from(bucket: \"bucket\")\r\n |> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n |> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id )\r\n |> filter(fn: (r) => r[\"_measurement\"] == \"mem\")\r\n |> filter(fn: (r) => r[\"_field\"] == field )\r\n |> map(fn: (r) => ({ r with\r\n _field: r._measurement + \"_\" + r._field\r\n }))\r\n |> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n |> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\n\r\n\r\n\r\n\r\n\r\n", + "editMode": "advanced", + "name": "", + "builderConfig": { + "buckets": [], + "tags": [ + { + "key": "_measurement", + "values": [], + "aggregateFunctionType": "filter" + } + ], + "functions": [ + { + "name": "mean" + } + ], + "aggregateWindow": { + "period": "auto", + "fillValues": false + } + } + } + ], + "axes": { + "x": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + }, + "y": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + } + }, + "type": "xy", + "legend": {}, + "geom": "line", + "colors": [ + { + "id": "08c3469f-33ae-404b-876f-d05ec0913e47", + "type": "scale", + "hex": "#31C0F6", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "5cbfcd6f-407a-41d7-9d3e-2eb1987bead3", + "type": "scale", + "hex": "#A500A5", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "c5dfaa8b-92ae-416b-aa46-71f4718e8c24", + "type": "scale", + "hex": "#FF7E27", + "name": "Nineteen Eighty Four", + "value": 0 + } + ], + "note": "", + "showNoteWhenEmpty": false, + "xColumn": "_time", + "generateXAxisTicks": null, + "xTotalTicks": 0, + "xTickStart": 0, + "xTickStep": 0, + "yColumn": "_value", + "generateYAxisTicks": null, + "yTotalTicks": 0, + "yTickStart": 0, + "yTickStep": 0, + "shadeBelow": false, + "position": "overlaid", + "timeFormat": "", + "hoverDimension": "", + "legendColorizeRows": false, + "legendOpacity": 0, + "legendOrientationThreshold": 0 + } + } + }, + { + "type": "view", + "id": "091bf8e4c5e99000", + "attributes": { + "name": "all metrics (Clone)", + "properties": { + "shape": "chronograf-v2", + "queries": [ + { + "text": "cpu = from(bucket: \"bucket\")\r\n|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n|> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id )\r\n|> filter(fn: (r) => r[\"_measurement\"] == \"cpu\")\r\n|> filter(fn: (r) => r[\"_field\"] == \"usage_idle\" or r[\"_field\"] == \"usage_system\" or r[\"_field\"] == \"usage_user\" )\r\n|> filter(fn: (r) => r[\"cpu\"] == \"cpu-total\")\r\n|> map(fn: (r) => ({ r with\r\n _field: r._measurement + \"_\" + r._field\r\n}))\r\n|> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\n\r\ndisk = from(bucket: \"bucket\")\r\n|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n|> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id )\r\n|> filter(fn: (r) => r[\"_measurement\"] == \"disk\" )\r\n|> filter(fn: (r) => r[\"_field\"] == \"used_percent\" or r[\"_field\"] == \"free\")\r\n|> filter(fn: (r) => r[\"path\"] == \"/\")\r\n|> map(fn: (r) => ({ r with\r\n _field: r._measurement + \"_\" + r._field\r\n}))\r\n|> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\n\r\nmem = from(bucket: \"bucket\")\r\n|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n|> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id )\r\n|> filter(fn: (r) => r[\"_measurement\"] == \"mem\")\r\n|> filter(fn: (r) => r[\"_field\"] == \"used_percent\" or r[\"_field\"] == \"free\" )\r\n|> map(fn: (r) => ({ r with\r\n _field: r._measurement + \"_\" + r._field\r\n}))\r\n|> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\n\r\nunion(tables: [cpu, disk, mem])\r\n\r\n\r\n\r\n", + "editMode": "advanced", + "name": "", + "builderConfig": { + "buckets": [], + "tags": [ + { + "key": "_measurement", + "values": [], + "aggregateFunctionType": "filter" + } + ], + "functions": [ + { + "name": "mean" + } + ], + "aggregateWindow": { + "period": "auto", + "fillValues": false + } + } + } + ], + "axes": { + "x": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + }, + "y": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + } + }, + "type": "xy", + "legend": {}, + "geom": "line", + "colors": [ + { + "id": "08c3469f-33ae-404b-876f-d05ec0913e47", + "type": "scale", + "hex": "#31C0F6", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "5cbfcd6f-407a-41d7-9d3e-2eb1987bead3", + "type": "scale", + "hex": "#A500A5", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "c5dfaa8b-92ae-416b-aa46-71f4718e8c24", + "type": "scale", + "hex": "#FF7E27", + "name": "Nineteen Eighty Four", + "value": 0 + } + ], + "note": "", + "showNoteWhenEmpty": false, + "xColumn": "_time", + "generateXAxisTicks": null, + "xTotalTicks": 0, + "xTickStart": 0, + "xTickStep": 0, + "yColumn": "_value", + "generateYAxisTicks": null, + "yTotalTicks": 0, + "yTickStart": 0, + "yTickStep": 0, + "shadeBelow": false, + "position": "overlaid", + "timeFormat": "", + "hoverDimension": "", + "legendColorizeRows": false, + "legendOpacity": 0, + "legendOrientationThreshold": 0 + } + } + }, + { + "id": "091ad8610e70a000", + "type": "variable", + "attributes": { + "name": "deployment_id", + "arguments": { + "type": "query", + "values": { + "query": "import \"influxdata/influxdb/schema\"\r\n\r\nschema.tagValues(bucket: \"bucket\", tag: \"deployment_id\")\r\n", + "language": "flux" + } + }, + "selected": [] + }, + "relationships": { + "label": { + "data": [] + } + } + }, + { + "id": "091ad90b9730a000", + "type": "variable", + "attributes": { + "name": "variable", + "arguments": { + "type": "constant", + "values": [ + "cpu_usage_idle", + "cpu_usage_system", + "cpu_usage_user", + "disk_free", + "disk_used_percent", + "mem_free", + "mem_used_percent", + "availability" + ] + }, + "selected": [ + "cpu_usage_idle" + ] + }, + "relationships": { + "label": { + "data": [] + } + } + } + ] + }, + "labels": [] +} \ No newline at end of file diff --git a/influxdb/dashboards/psl_variable_analysis.json b/influxdb/dashboards/psl_variable_analysis.json new file mode 100644 index 0000000..35e4285 --- /dev/null +++ b/influxdb/dashboards/psl_variable_analysis.json @@ -0,0 +1,470 @@ +{ + "meta": { + "version": "1", + "type": "dashboard", + "name": "psl variable analysis-Template", + "description": "template created from dashboard: psl variable analysis" + }, + "content": { + "data": { + "type": "dashboard", + "attributes": { + "name": "psl variable analysis", + "description": "" + }, + "relationships": { + "label": { + "data": [] + }, + "cell": { + "data": [ + { + "type": "cell", + "id": "091ad721f7e99000" + }, + { + "type": "cell", + "id": "091ad721fc699000" + }, + { + "type": "cell", + "id": "091ad721fda99000" + } + ] + }, + "variable": { + "data": [ + { + "type": "variable", + "id": "091ad8610e70a000" + }, + { + "type": "variable", + "id": "091ad90b9730a000" + } + ] + } + } + }, + "included": [ + { + "id": "091ad721f7e99000", + "type": "cell", + "attributes": { + "x": 0, + "y": 8, + "w": 12, + "h": 4 + }, + "relationships": { + "view": { + "data": { + "type": "view", + "id": "091ad721f7e99000" + } + } + } + }, + { + "id": "091ad721fc699000", + "type": "cell", + "attributes": { + "x": 0, + "y": 4, + "w": 12, + "h": 4 + }, + "relationships": { + "view": { + "data": { + "type": "view", + "id": "091ad721fc699000" + } + } + } + }, + { + "id": "091ad721fda99000", + "type": "cell", + "attributes": { + "x": 0, + "y": 0, + "w": 12, + "h": 4 + }, + "relationships": { + "view": { + "data": { + "type": "view", + "id": "091ad721fda99000" + } + } + } + }, + { + "type": "view", + "id": "091ad721f7e99000", + "attributes": { + "name": "anomaly and drift", + "properties": { + "shape": "chronograf-v2", + "queries": [ + { + "text": "from(bucket: \"bucket\")\r\n|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n|> filter(fn: (r) => r[\"_measurement\"] == \"psl\")\r\n|> filter(fn: (r) => r[\"_field\"] == v.variable + \"_anomaly\" or r[\"_field\"] == v.variable + \"_drift\")\r\n|> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id)\r\n|> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n|> aggregateWindow(every: 1m, fn: last, createEmpty: false)\r\n|> map(fn: (r) => ({\r\n r with\r\n _value:\r\n if r._value then 1\r\n else 0\r\n}))\r\n", + "editMode": "advanced", + "name": "", + "builderConfig": { + "buckets": [], + "tags": [ + { + "key": "_measurement", + "values": [], + "aggregateFunctionType": "filter" + } + ], + "functions": [ + { + "name": "mean" + } + ], + "aggregateWindow": { + "period": "auto", + "fillValues": false + } + } + } + ], + "axes": { + "x": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + }, + "y": { + "bounds": [ + "0", + "1" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "2", + "scale": "linear" + } + }, + "type": "xy", + "legend": {}, + "geom": "line", + "colors": [ + { + "id": "17673c24-77b4-4337-8775-b136210f59c7", + "type": "scale", + "hex": "#31C0F6", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "1cb8ce4b-a263-4ba7-9443-e39042afa498", + "type": "scale", + "hex": "#A500A5", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "09af4c3e-ac17-4acc-bbae-5f2d1286b681", + "type": "scale", + "hex": "#FF7E27", + "name": "Nineteen Eighty Four", + "value": 0 + } + ], + "note": "", + "showNoteWhenEmpty": false, + "xColumn": "_time", + "generateXAxisTicks": null, + "xTotalTicks": 0, + "xTickStart": 0, + "xTickStep": 0, + "yColumn": "_value", + "generateYAxisTicks": null, + "yTotalTicks": 0, + "yTickStart": 0, + "yTickStep": 0, + "shadeBelow": false, + "position": "overlaid", + "timeFormat": "", + "hoverDimension": "", + "legendColorizeRows": false, + "legendOpacity": 0, + "legendOrientationThreshold": 0 + } + } + }, + { + "type": "view", + "id": "091ad721fc699000", + "attributes": { + "name": "mae", + "properties": { + "shape": "chronograf-v2", + "queries": [ + { + "text": "from(bucket: \"bucket\")\n|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\n|> filter(fn: (r) => r[\"_measurement\"] == \"psl\")\n|> filter(fn: (r) => r[\"_field\"] == v.variable + \"_mean_absolute_error\")\n|> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id)\n|> keep(columns: [\"_time\", \"_field\",\"_value\"])\n|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\n", + "editMode": "advanced", + "name": "", + "builderConfig": { + "buckets": [], + "tags": [ + { + "key": "_measurement", + "values": [], + "aggregateFunctionType": "filter" + } + ], + "functions": [ + { + "name": "mean" + } + ], + "aggregateWindow": { + "period": "auto", + "fillValues": false + } + } + } + ], + "axes": { + "x": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + }, + "y": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "2", + "scale": "linear" + } + }, + "type": "xy", + "legend": {}, + "geom": "line", + "colors": [ + { + "id": "17673c24-77b4-4337-8775-b136210f59c7", + "type": "scale", + "hex": "#31C0F6", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "1cb8ce4b-a263-4ba7-9443-e39042afa498", + "type": "scale", + "hex": "#A500A5", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "09af4c3e-ac17-4acc-bbae-5f2d1286b681", + "type": "scale", + "hex": "#FF7E27", + "name": "Nineteen Eighty Four", + "value": 0 + } + ], + "note": "", + "showNoteWhenEmpty": false, + "xColumn": "_time", + "generateXAxisTicks": null, + "xTotalTicks": 0, + "xTickStart": 0, + "xTickStep": 0, + "yColumn": "_value", + "generateYAxisTicks": null, + "yTotalTicks": 0, + "yTickStart": 0, + "yTickStep": 0, + "shadeBelow": false, + "position": "overlaid", + "timeFormat": "", + "hoverDimension": "", + "legendColorizeRows": false, + "legendOpacity": 0, + "legendOrientationThreshold": 0 + } + } + }, + { + "type": "view", + "id": "091ad721fda99000", + "attributes": { + "name": "prediction vs exactly used input value", + "properties": { + "shape": "chronograf-v2", + "queries": [ + { + "text": "from(bucket: \"bucket\")\r\n|> range(start: v.timeRangeStart, stop: v.timeRangeStop)\r\n|> filter(fn: (r) => r[\"_measurement\"] == \"psl\")\r\n|> filter(fn: (r) => r[\"_field\"] == \"input_\" + v.variable or r[\"_field\"] == v.variable)\r\n|> filter(fn: (r) => r[\"deployment_id\"] == v.deployment_id)\r\n|> keep(columns: [\"_time\", \"_field\",\"_value\"])\r\n|> aggregateWindow(every: 1m, fn: mean, createEmpty: false)\r\n", + "editMode": "advanced", + "name": "", + "builderConfig": { + "buckets": [], + "tags": [ + { + "key": "_measurement", + "values": [], + "aggregateFunctionType": "filter" + } + ], + "functions": [ + { + "name": "mean" + } + ], + "aggregateWindow": { + "period": "auto", + "fillValues": false + } + } + } + ], + "axes": { + "x": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + }, + "y": { + "bounds": [ + "", + "" + ], + "label": "", + "prefix": "", + "suffix": "", + "base": "10", + "scale": "linear" + } + }, + "type": "xy", + "legend": {}, + "geom": "line", + "colors": [ + { + "id": "08c3469f-33ae-404b-876f-d05ec0913e47", + "type": "scale", + "hex": "#31C0F6", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "5cbfcd6f-407a-41d7-9d3e-2eb1987bead3", + "type": "scale", + "hex": "#A500A5", + "name": "Nineteen Eighty Four", + "value": 0 + }, + { + "id": "c5dfaa8b-92ae-416b-aa46-71f4718e8c24", + "type": "scale", + "hex": "#FF7E27", + "name": "Nineteen Eighty Four", + "value": 0 + } + ], + "note": "", + "showNoteWhenEmpty": false, + "xColumn": "_time", + "generateXAxisTicks": null, + "xTotalTicks": 0, + "xTickStart": 0, + "xTickStep": 0, + "yColumn": "_value", + "generateYAxisTicks": null, + "yTotalTicks": 0, + "yTickStart": 0, + "yTickStep": 0, + "shadeBelow": false, + "position": "overlaid", + "timeFormat": "", + "hoverDimension": "", + "legendColorizeRows": false, + "legendOpacity": 0, + "legendOrientationThreshold": 0 + } + } + }, + { + "id": "091ad8610e70a000", + "type": "variable", + "attributes": { + "name": "deployment_id", + "arguments": { + "type": "query", + "values": { + "query": "import \"influxdata/influxdb/schema\"\r\n\r\nschema.tagValues(bucket: \"bucket\", tag: \"deployment_id\")\r\n", + "language": "flux" + } + }, + "selected": [] + }, + "relationships": { + "label": { + "data": [] + } + } + }, + { + "id": "091ad90b9730a000", + "type": "variable", + "attributes": { + "name": "variable", + "arguments": { + "type": "constant", + "values": [ + "cpu_usage_idle", + "cpu_usage_system", + "cpu_usage_user", + "disk_free", + "disk_used_percent", + "mem_free", + "mem_used_percent", + "availability" + ] + }, + "selected": [ + "cpu_usage_idle" + ] + }, + "relationships": { + "label": { + "data": [] + } + } + } + ] + }, + "labels": [] +} \ No newline at end of file diff --git a/influxdb/variables/deployment_id.json b/influxdb/variables/deployment_id.json new file mode 100644 index 0000000..d8ded6a --- /dev/null +++ b/influxdb/variables/deployment_id.json @@ -0,0 +1,35 @@ +{ + "meta": { + "version": "1", + "type": "variable", + "name": "deployment_id-Template", + "description": "template created from variable: deployment_id" + }, + "content": { + "data": { + "type": "variable", + "id": "091ad8610e70a000", + "attributes": { + "name": "deployment_id", + "arguments": { + "type": "query", + "values": { + "query": "import \"influxdata/influxdb/schema\"\r\n\r\nschema.tagValues(bucket: \"bucket\", tag: \"deployment_id\")\r\n", + "language": "flux" + } + }, + "selected": [] + }, + "relationships": { + "variable": { + "data": [] + }, + "label": { + "data": [] + } + } + }, + "included": [] + }, + "labels": [] +} \ No newline at end of file diff --git a/influxdb/variables/variable.json b/influxdb/variables/variable.json new file mode 100644 index 0000000..56eaf7a --- /dev/null +++ b/influxdb/variables/variable.json @@ -0,0 +1,43 @@ +{ + "meta": { + "version": "1", + "type": "variable", + "name": "variable-Template", + "description": "template created from variable: variable" + }, + "content": { + "data": { + "type": "variable", + "id": "091ad90b9730a000", + "attributes": { + "name": "variable", + "arguments": { + "type": "constant", + "values": [ + "cpu_usage_idle", + "cpu_usage_system", + "cpu_usage_user", + "disk_free", + "disk_used_percent", + "mem_free", + "mem_used_percent", + "availability" + ] + }, + "selected": [ + "cpu_usage_idle" + ] + }, + "relationships": { + "variable": { + "data": [] + }, + "label": { + "data": [] + } + } + }, + "included": [] + }, + "labels": [] +} \ No newline at end of file diff --git a/openapi.yaml b/openapi.yaml index 16dbbdc..f6c52d8 100644 --- a/openapi.yaml +++ b/openapi.yaml @@ -77,7 +77,6 @@ paths: summary: Adds a resource to be learn tags: - SelfLearning - x-openapi-router-controller: psl.controllers.self_learning_controller /deployments/{DeploymentID}: delete: description: Stops a deployment from being supervised with SelfLearning algorithms. @@ -132,7 +131,6 @@ paths: summary: Stops SelfLearning a Deployment tags: - SelfLearning - x-openapi-router-controller: psl.controllers.self_learning_controller components: parameters: DeploymentID: @@ -202,8 +200,13 @@ components: schemas: Deployment: description: Deployment - example: 123e4567-e89b-12d3-a456-426614174000 - type: string + example: + deployment_id: 123e4567-e89b-12d3-a456-426614174000 + properties: + deployment_id: + description: id of the deployment + type: string + type: object DeploymentID: example: 123e4567-e89b-12d3-a456-426614174000 description: Id of the deployment @@ -212,20 +215,15 @@ components: properties: timestamp: format: date-time - title: timestamp type: string message: description: User friendly message for the error. - title: message type: string class_name: description: Class of the underlying error. only visible in development environments - title: class_name type: string debug_message: description: Field with debug information, only visible in development environments - title: debug_message type: string - title: Error type: object diff --git a/piacere-build/docker-compose.yaml b/piacere-build/docker-compose.yaml new file mode 100644 index 0000000..bd4f1e0 --- /dev/null +++ b/piacere-build/docker-compose.yaml @@ -0,0 +1,7 @@ +services: + psl: + build: + context: ${PSL_BASE_PATH}. + dockerfile: Dockerfile + args: + BUILDKIT_INLINE_CACHE: 1 # For multistage docker diff --git a/psl/test/test_self_learning_flow.py b/psl/test/test_self_learning_flow.py new file mode 100644 index 0000000..cd49a88 --- /dev/null +++ b/psl/test/test_self_learning_flow.py @@ -0,0 +1,9 @@ +from psl.flows import self_learning_flow +import urllib3 + +urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) + +while True: + valid_predictions, total_deployments, total_time = self_learning_flow.run() + if valid_predictions < total_deployments: + break diff --git a/release/docker-compose.yaml b/release/docker-compose.yaml new file mode 100644 index 0000000..16948d0 --- /dev/null +++ b/release/docker-compose.yaml @@ -0,0 +1,3 @@ +services: + psl: + image: ${IMAGE_PSL:?err} diff --git a/requirements.txt b/requirements.txt index 9f7fe39..4881cc5 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,46 +1,55 @@ -itsdangerous==2.0.1 -connexion[swagger-ui] >= 2.6.0; python_version>="3.6" -# 2.3 is the last version that supports python 3.4-3.5 -connexion[swagger-ui] <= 2.3.0; python_version=="3.5" or python_version=="3.4" -# connexion requires werkzeug but connexion < 2.4.0 does not install werkzeug -# we must peg werkzeug versions below to fix connexion -# https://github.com/zalando/connexion/pull/1044 -werkzeug == 0.16.1; python_version=="3.5" or python_version=="3.4" -swagger-ui-bundle >= 0.0.2 -python_dateutil >= 2.6.0 -setuptools >= 21.0.0 -Flask == 1.1.2 - - -# Application specific -confuse==1.7.0 -# requires gcc apispec==5.1.1 apispec-webframeworks==0.5.2 arrow==1.1.1 -# requires additionally: libffi-dev, musl-dev +attrs==23.1.0 cairocffi==1.2.0 certifi==2021.10.8 +cffi==1.15.1 +charset-normalizer==3.1.0 +click==8.1.3 +clickclick==20.10.2 +confuse==1.7.0 +connexion==2.14.2 +cycler==0.11.0 +Flask==2.1.0 +idna==3.4 +importlib-metadata==6.6.0 +inflection==0.5.1 influxdb-client==1.21.0 iso8601==0.1.16 -# we try to fix scypi version as it creates problems -scipy==1.7.3 -# requires additionally: zlib-dev +itsdangerous==2.0.1 +Jinja2==3.1.2 +joblib==1.2.0 +jsonschema==4.17.3 +kiwisolver==1.4.4 +MarkupSafe==2.1.3 marshmallow==3.14.0 matplotlib==3.4.3 numpy==1.21.2 -# requires additionally: g++, make +packaging==23.1 pandas==1.3.3 -# requires additionally: cairo-dev +patsy==0.5.3 +Pillow==9.5.0 pycairo==1.20.1 -PyQt5==5.15.4 -# requires additionally: openblas-dev lapack-dev +pycparser==2.21 +PyJWT==2.3.0 +pyparsing==3.0.9 +pyrsistent==0.19.3 +python-dateutil==2.8.2 +pytz==2023.3 +PyYAML==6.0 +requests==2.31.0 river==0.9.0 +Rx==3.2.0 scikit-learn==1.0 +scipy==1.7.3 seaborn==0.11.2 six==1.16.0 statsmodels==0.13.2 +swagger-ui-bundle==0.0.9 +threadpoolctl==3.1.0 tqdm==4.62.3 urllib3==1.26.7 webargs==8.0.1 -pyjwt==2.3.0 \ No newline at end of file +Werkzeug==2.2.3 +zipp==3.15.0 \ No newline at end of file diff --git a/setup.py b/setup.py index 23787a2..3b72a3d 100644 --- a/setup.py +++ b/setup.py @@ -27,9 +27,9 @@ setup( url="", keywords=["OpenAPI", "PIACERE Performance SelfLearning"], install_requires=REQUIRES, - packages=find_packages("src\"), - package_dir={"": "src\"}, - package_data={'': ['src\/openapi/openapi.yaml']}, + packages=find_packages("src/"), + package_dir={"": "src/"}, + package_data={'': ['src/openapi/openapi.yaml']}, include_package_data=True, entry_points={ 'console_scripts': ['psl=psl.__main__:main']}, @@ -37,4 +37,3 @@ setup( No description provided (generated by Openapi Generator https://github.com/openapitools/openapi-generator) """ ) - diff --git a/src/psl/adapters/csv_to_metric_source.py b/src/psl/adapters/csv_to_metric_source.py index cf91fa3..ca8e86b 100644 --- a/src/psl/adapters/csv_to_metric_source.py +++ b/src/psl/adapters/csv_to_metric_source.py @@ -31,10 +31,11 @@ class CSVToMetricsSource(MetricSource): file_path, header=0, sep=";", skiprows=range(1, self.start_row), nrows=n ) # ',index_col='time' self.start_row += n + if data_frame.empty: + return data_frame data_frame[time_column_name] = pandas.to_datetime( data_frame[time_column_name] ).dt.tz_localize(None) - # this may be unecessary in next version data_frame.rename(columns={time_column_name: feat_name}, inplace=True) - data_frame = data_frame[[lab_name, feat_name]] + # we need to store the data in the influx for rendering purposes return data_frame diff --git a/src/psl/adapters/influxdb_to_influxdb.py b/src/psl/adapters/influxdb_to_influxdb.py index 660eb34..35577dc 100644 --- a/src/psl/adapters/influxdb_to_influxdb.py +++ b/src/psl/adapters/influxdb_to_influxdb.py @@ -9,7 +9,7 @@ import pandas influxdb_config = config["influxdb"] feat_name = influxdb_config["feat_name"].get() lab_name = influxdb_config["lab_name"].get() -focus_metric = influxdb_config["focus_metric"].get() +measurement_name = influxdb_config["measurement_name"].get() def get_conn_opts_from_influxdb_config(influxdb_config): @@ -24,46 +24,114 @@ conn_opts = get_conn_opts_from_influxdb_config(influxdb_config) bucket_name = influxdb_config["bucket_name"].get() -def save_prediction(prediction, prediction_datetime, deployment_id): +def save_prediction( + prediction, + lab_names, + prediction_datetime, + deployment_id, + doml_element_name, + doml_element_type, + host, + input_datetime + ): logging.debug( - "Saving predict {} for deployment {} into influxdb".format( - prediction, deployment_id + "Saving predict {} for deployment {}/{}/{}/{} into influxdb".format( + prediction, deployment_id, doml_element_name, doml_element_type, host ) ) with InfluxDBClient(**conn_opts) as client: - # try: point_settings = PointSettings() point_settings.add_default_tag("deployment_id", deployment_id) + point_settings.add_default_tag("doml_element_name", doml_element_name) + point_settings.add_default_tag("doml_element_type", doml_element_type) + point_settings.add_default_tag("host", host) write_api = client.write_api( write_options=SYNCHRONOUS, point_settings=point_settings ) - cpu_usage_idle = float(prediction[0]) - mean_absolute_error = float(prediction[1]) - anomaly = bool(prediction[2]) - drift = bool(prediction[3]) - # https://community.influxdata.com/t/storing-additional-timestamp-type-information-as-a-field/6082 - # influxdb no admite timestamps que ya me parecia raro - # .astype(int) / 10**9 + point = ( + Point(measurement_name) + .measurement(measurement_name) + .time(input_datetime) + ) + current_datetime = pandas.Timestamp.utcnow().replace(tzinfo=None) time_delta = prediction_datetime - current_datetime prediction_hours_in_advance = time_delta.total_seconds() / (60 * 60) - point = ( - Point("psl") - .measurement("psl") - .field("cpu_usage_idle", cpu_usage_idle) - .field("mean_absolute_error", mean_absolute_error) - .field("anomaly", anomaly) - .field("drift", drift) - .field("prediction_hours_in_advance", prediction_hours_in_advance) + + field_added = False + for index, lab_name in enumerate(lab_names): + try: + value = float(prediction[index][0]) + mean_absolute_error = float(prediction[index][1]) + anomaly = bool(prediction[index][2]) + drift = bool(prediction[index][3]) + (point + .field(lab_name, value) + .field("{}_mean_absolute_error".format(lab_name), mean_absolute_error) + .field("{}_anomaly".format(lab_name), anomaly) + .field("{}_drift".format(lab_name), drift) + .field("{}_prediction_hours_in_advance".format(lab_name), prediction_hours_in_advance)) + field_added = True + except Exception: + None + + if field_added: + try: + write_api.write(bucket=bucket_name, record=point) + except Exception: + logging.error( + "accesing influxdb for deployment_id: {}".format(deployment_id) + ) + return + + +def save_input(metrics, deployment_id, doml_element_name, doml_element_type, host, lab_names): + logging.debug( + "Saving input metrics for deployment {}/{}/{}/{} into influxdb".format( + deployment_id, doml_element_name, doml_element_type, host ) + ) + with InfluxDBClient(**conn_opts) as client: + point_settings = PointSettings() + point_settings.add_default_tag("deployment_id", deployment_id) + point_settings.add_default_tag("doml_element_name", doml_element_name) + point_settings.add_default_tag("doml_element_type", doml_element_type) + point_settings.add_default_tag("host", host) + + write_api = client.write_api( + write_options=SYNCHRONOUS, point_settings=point_settings + ) + + for index, row in metrics.iterrows(): + time = row[feat_name] + point = ( + Point(measurement_name) + .measurement(measurement_name) + .time(time) + ) - write_api.write(bucket=bucket_name, record=point) + field_added = False + for lab_name in lab_names: + value = None + try: + value = getattr(row, lab_name) + if pandas.isnull(value): + continue + float_value = float(value) + point.field("input_{}".format(lab_name), float_value) + field_added = True + except Exception: + None - # except Exception: - # logging.error( - # "accesing influxdb for deployment_id: {}".format(deployment_id) - # ) + if field_added: + try: + logging.debug("writing deployment_id {}/{}/{}/{} point: {}".format(deployment_id, doml_element_name, doml_element_type, host, point.to_line_protocol())) + write_api.write(bucket=bucket_name, record=point) + except Exception: + logging.error( + "accesing influxdb for deployment_id {}/{}/{}/{}".format(deployment_id, doml_element_name, doml_element_type, host) + ) return diff --git a/src/psl/adapters/influxdb_to_metric_source.py b/src/psl/adapters/influxdb_to_metric_source.py index cb9317b..fe41398 100644 --- a/src/psl/adapters/influxdb_to_metric_source.py +++ b/src/psl/adapters/influxdb_to_metric_source.py @@ -10,7 +10,6 @@ from operator import itemgetter influxdb_config = config["influxdb"] feat_name = influxdb_config["feat_name"].get() lab_name = influxdb_config["lab_name"].get() -focus_metric = influxdb_config["focus_metric"].get() def get_conn_opts_from_influxdb_config(influxdb_config): @@ -26,35 +25,76 @@ train_time_range_start = influxdb_config["train_time_range_start"].get() predict_time_range_start = influxdb_config["predict_time_range_start"].get() bucket_name = influxdb_config["bucket_name"].get() aggregate_sampling = influxdb_config["aggregate_sampling"].get() +telegraf_interval = influxdb_config["telegraf_interval"].get() QUERY_TEMPLATE = """ -from(bucket: "{bucket}") - |> range(start: {start}) +import "date" +import "system" + +bucket = "{bucket}" +start = {start} +deploymentId = "{deployment_id}" +telegrafInterval = {telegraf_interval} +discardLevel = int(v: duration(v: uint(v: telegrafInterval) + uint(v: 5s)))/1000000000 +aggregateSampling = {aggregate_sampling} +currentTime = system.time() +initialTime = date.sub(from: currentTime, d: duration(v: uint(v: -start) - uint(v: telegrafInterval) - uint(v: telegrafInterval))) + +deploymentData = from(bucket: bucket ) + |> range(start: start ) + |> filter(fn: (r) => r["deployment_id"] == deploymentId ) + +cpu = deploymentData |> filter(fn: (r) => r["_measurement"] == "cpu") - |> filter(fn: (r) => r["_field"] == "usage_idle" or r["_field"] == "usage_system" or r["_field"] == "usage_user") + |> filter(fn: (r) => r["_field"] == "usage_idle") |> filter(fn: (r) => r["cpu"] == "cpu-total") - |> filter(fn: (r) => r["deployment_id"] == "{deployment_id}") |> map(fn: (r) => ({{ r with - _field: r._measurement + "_" + r._field - }})) - |> keep(columns: ["_time", "_field","_value"]) - |> aggregateWindow(every: {aggregate_sampling}, fn: mean, createEmpty: false) - |> yield(name: "mean") -""" - + _field: r._measurement + "_" + "used_percent" + }})) + |> map(fn: (r) => ({{ r with + _value: 100.0 - float(v: r._value) + }})) + |> keep(columns: ["_time", "_field","_value","doml_element_name","doml_element_type","host"]) -# |> filter(fn: (r) => r["_field"] == "usage_idle") +disk = deploymentData + |> filter(fn: (r) => r["_measurement"] == "disk" ) + |> filter(fn: (r) => r["_field"] == "used_percent" ) + |> filter(fn: (r) => r["path"] == "/") + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + r._field + }})) + |> keep(columns: ["_time", "_field","_value","doml_element_name","doml_element_type","host"]) -# |> filter(fn: (r) => r["_measurement"] == "cpu") -# |> filter(fn: (r) => r["_field"] == "usage_idle" or r["_field"] == "usage_system" or r["_field"] == "usage_user") -# |> filter(fn: (r) => r["cpu"] == "cpu-total") +mem = deploymentData + |> filter(fn: (r) => r["_measurement"] == "mem") + |> filter(fn: (r) => r["_field"] == "used_percent" ) + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + r._field + }})) + |> keep(columns: ["_time", "_field","_value","doml_element_name","doml_element_type","host"]) -# |> filter(fn: (r) => r["_measurement"] == "disk") -# |> filter(fn: (r) => r["_field"] == "free" or r["_field"] == "used_percent") -# |> filter(fn: (r) => r["path"] == "/") +availability = deploymentData + |> filter(fn: (r) => r["_measurement"] == "system") + |> filter(fn: (r) => r["_field"] == "uptime") + |> elapsed() + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + "availability_percent" + }})) + |> map(fn: (r) => ({{ r with + _value: if r.elapsed > discardLevel then 0 else 100 + }})) + |> aggregateWindow(every: telegrafInterval, fn: mean, createEmpty: true) // create empty to true create missing points of elements not submmiting metrics + |> range(start: initialTime) //we adjust initial time to remove some extra null added at the beginning + |> fill(column: "_value", value: 0.0) +// |> tail(n: 1000000,offset: 1) + |> keep(columns: ["_time", "_field","_value","doml_element_name","doml_element_type","host"]) -# |> filter(fn: (r) => r["_measurement"] == "mem") -# |> filter(fn: (r) => r["_field"] == "free" or r["_field"] == "used_percent") +union(tables: [cpu, disk, mem, availability]) + |> aggregateWindow(every: aggregateSampling, fn: mean, createEmpty: false) + |> group(columns: [ "_time","doml_element_name","doml_element_type","host","_field"]) + |> mean() + |> group(columns: ["doml_element_name","doml_element_type","host","_field"]) +""" def request_metrics_to_influxdb(time_range, deployment_id, number_of_records): logging.debug("requesting Influxdb for latest {} metrics".format(time_range)) @@ -63,46 +103,169 @@ def request_metrics_to_influxdb(time_range, deployment_id, number_of_records): "start": time_range, "deployment_id": str(deployment_id), "aggregate_sampling": aggregate_sampling, + "telegraf_interval": telegraf_interval, } query = QUERY_TEMPLATE.format(**query_data) with InfluxDBClient(**conn_opts) as client: try: query_api = client.query_api() data_frame = query_api.query_data_frame(query=query) - # the number of row multiply by each additional metric, we group by time + logging.debug("Influxdb query result: {}".format(data_frame)) + # we group by time and we get the last timestamp data_frame_grouped = data_frame.groupby("_time") - # we take the last number_of_records https://stackoverflow.com/a/52895848 + # drop the last timestamp as it does not contain availability data_frame = pandas.concat( deque(map(itemgetter(1), data_frame_grouped), maxlen=number_of_records) ) - data_frame_grouped = data_frame.groupby("_time") + # we group by time, doml_element_name, doml_element_type + data_frame_grouped = data_frame.groupby(["_time", "doml_element_name", "doml_element_type", "host"]) # we create a new dataframe data_frame = pandas.DataFrame( [ { + feat_name: pandas.to_datetime(time_doml_element_name[0], utc=True).replace(tzinfo=None), **dict(values[["_field", "_value"]].values), - feat_name: pandas.to_datetime(time).replace(tzinfo=None), + "doml_element_name": time_doml_element_name[1], + "doml_element_type": time_doml_element_name[2], + "host": time_doml_element_name[3], } - for time, values in data_frame_grouped + for time_doml_element_name, values in data_frame_grouped ] ) # predictor_utils.read_piacere_data establishes the index but the next step data_reparing dissable it # it also changes time to datetime but this is already done therefore I will skip it # predictor_utils.data_preparing changes _time to moment ... but why here and not when creating the pandas.DataFrame? + logging.debug("Output Data Frame: {}".format(data_frame)) + return data_frame + except Exception as error: + print(error) + logging.error( + "accesing influxdb for deployment_id: {}".format(deployment_id) + ) + return None + +QUERY_TEMPLATE_TRAINING = """ +import "date" +import "system" - # this may be unecessary in next version - data_frame.rename(columns={focus_metric: lab_name}, inplace=True) - data_frame = data_frame[[lab_name, feat_name]] +bucket = "{bucket}" +start = {start} +deploymentId = "{deployment_id}" +domlElementName = "{doml_element_name}" +domlElementType = "{doml_element_type}" +telegrafInterval = {telegraf_interval} +discardLevel = int(v: duration(v: uint(v: telegrafInterval) + uint(v: 5s)))/1000000000 +aggregateSampling = {aggregate_sampling} +currentTime = system.time() +initialTime = date.sub(from: currentTime, d: duration(v: uint(v: -start) - uint(v: telegrafInterval) - uint(v: telegrafInterval))) +deploymentData = from(bucket: bucket ) + |> range(start: start ) + |> filter(fn: (r) => r["deployment_id"] == deploymentId ) + |> filter(fn: (r) => r["doml_element_name"] == domlElementName ) + |> filter(fn: (r) => r["doml_element_type"] == domlElementType ) + +cpu = deploymentData + |> filter(fn: (r) => r["_measurement"] == "cpu") + |> filter(fn: (r) => r["_field"] == "usage_idle") + |> filter(fn: (r) => r["cpu"] == "cpu-total") + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + "used_percent" + }})) + |> map(fn: (r) => ({{ r with + _value: 100.0 - float(v: r._value) + }})) + |> keep(columns: ["_time", "_field","_value"]) + +disk = deploymentData + |> filter(fn: (r) => r["_measurement"] == "disk" ) + |> filter(fn: (r) => r["_field"] == "used_percent" ) + |> filter(fn: (r) => r["path"] == "/") + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + r._field + }})) + |> keep(columns: ["_time", "_field","_value"]) + +mem = deploymentData + |> filter(fn: (r) => r["_measurement"] == "mem") + |> filter(fn: (r) => r["_field"] == "used_percent" ) + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + r._field + }})) + |> keep(columns: ["_time", "_field","_value"]) + +availability = deploymentData + |> filter(fn: (r) => r["_measurement"] == "system") + |> filter(fn: (r) => r["_field"] == "uptime") + |> elapsed() + |> map(fn: (r) => ({{ r with + _field: r._measurement + "_" + "availability_percent" + }})) + |> map(fn: (r) => ({{ r with + _value: if r.elapsed > discardLevel then 0 else 100 + }})) + |> aggregateWindow(every: telegrafInterval, fn: mean, createEmpty: true) // create empty to true create missing points of elements not submmiting metrics + |> range(start: initialTime) //we adjust initial time to remove some extra null added at the beginning + |> fill(column: "_value", value: 0.0) +// |> tail(n: 1000000,offset: 1) + |> keep(columns: ["_time", "_field","_value"]) + +union(tables: [cpu, disk, mem, availability]) + |> aggregateWindow(every: aggregateSampling, fn: mean, createEmpty: false) + |> group(columns: [ "_time", "_field"]) + |> mean() + |> group(columns: ["_field"]) + +""" + +def request_doml_element_name_metrics_to_influxdb(time_range, deployment_id, doml_element_name, doml_element_type, number_of_records): + logging.debug("requesting Influxdb for latest {} metrics for doml_element {}/{}/{}".format(time_range, deployment_id, doml_element_name, doml_element_type)) + query_data = { + "bucket": bucket_name, + "start": time_range, + "deployment_id": str(deployment_id), + "doml_element_name": str(doml_element_name), + "doml_element_type": str(doml_element_type), + "aggregate_sampling": aggregate_sampling, + "telegraf_interval": telegraf_interval, + } + query = QUERY_TEMPLATE_TRAINING.format(**query_data) + with InfluxDBClient(**conn_opts) as client: + try: + query_api = client.query_api() + data_frame = query_api.query_data_frame(query=query) + logging.debug("Influxdb query result: {}".format(data_frame)) + # we group by time and we get the last timestamp + data_frame_grouped = data_frame.groupby("_time") + # drop the last timestamp as it does not contain availability + data_frame = pandas.concat( + deque(map(itemgetter(1), data_frame_grouped), maxlen=number_of_records) + ) + # we group by time, host and doml_element_name + data_frame_grouped = data_frame.groupby("_time") + # we create a new dataframe + data_frame = pandas.DataFrame( + [ + { + feat_name: pandas.to_datetime(time, utc=True).replace(tzinfo=None), + **dict(values[["_field", "_value"]].values), + } + for time, values in data_frame_grouped + ] + ) + # predictor_utils.read_piacere_data establishes the index but the next step data_reparing dissable it + # it also changes time to datetime but this is already done therefore I will skip it + # predictor_utils.data_preparing changes _time to moment ... but why here and not when creating the pandas.DataFrame? + logging.debug("Output Data Frame: {}".format(data_frame)) return data_frame - except Exception: + except Exception as error: + print(error) logging.error( "accesing influxdb for deployment_id: {}".format(deployment_id) ) return None - class InfluxdbToMetricSource(MetricSource): def get_latest_metrics(self, deployment_id): logging.debug( @@ -115,12 +278,31 @@ class InfluxdbToMetricSource(MetricSource): ) return metrics - def get_latest_n_metrics(self, deployment_id, n): + def get_latest_n_metrics(self, deployment_id, doml_element_name, n): logging.debug( - "Accessing Influxdb for latest {} metrics of deployment: {}".format( - n, deployment_id + "Accessing Influxdb for latest {} metrics of deployment: {} {}".format( + n, deployment_id, doml_element_name ) ) metrics = request_metrics_to_influxdb(train_time_range_start, deployment_id, n) return metrics + + def get_latest_metrics_doml_element_name(self, deployment_id, doml_element_name, doml_element_type): + logging.debug( + "Accessing Influxdb for latest metrics of deployments: {}".format( + deployment_id + ) + ) + metrics = request_doml_element_name_metrics_to_influxdb(predict_time_range_start, deployment_id, doml_element_name, doml_element_type, 1) + return metrics + + def get_latest_n_metrics_doml_element_name(self, deployment_id, doml_element_name, doml_element_type, n): + logging.debug( + "Accessing Influxdb for latest {} metrics of deployment: {}/{}/{}".format( + n, deployment_id, doml_element_name, doml_element_type + ) + ) + + metrics = request_doml_element_name_metrics_to_influxdb(train_time_range_start, deployment_id, doml_element_name, doml_element_type, n) + return metrics diff --git a/src/psl/adapters/predictor_to_predictor.py b/src/psl/adapters/predictor_to_predictor.py index b07888a..754ef89 100644 --- a/src/psl/adapters/predictor_to_predictor.py +++ b/src/psl/adapters/predictor_to_predictor.py @@ -6,6 +6,7 @@ from psl.adapters.influxdb_to_metric_source import InfluxdbToMetricSource from psl.predictor.predictor import train from psl.predictor.predictor import predict from river import stream +import psl.adapters.influxdb_to_influxdb as influxdb predictor_adapter_config = config["predictor_adapter"] @@ -16,80 +17,98 @@ horizon = predictor_adapter_config["horizon"].get() feat_name = predictor_adapter_config["feat_name"].get() models_path = predictor_adapter_config["models_path"].get() monitored_vars = predictor_adapter_config["monitored_vars"].get() -cpu_usage_idle_monitored_var = monitored_vars[0] -lab_name = cpu_usage_idle_monitored_var["lab_name"] -window_anom_detect = cpu_usage_idle_monitored_var["window_anom_detect"] -delta = cpu_usage_idle_monitored_var["delta"] -anom_factor = cpu_usage_idle_monitored_var["anom_factor"] -threshold = cpu_usage_idle_monitored_var["threshold"] -monitored_var = cpu_usage_idle_monitored_var["monitored_var"] +lab_names = [monitored_var["lab_name"] for monitored_var in monitored_vars] +window_anom_detects = [monitored_var["window_anom_detect"] for monitored_var in monitored_vars] +deltas = [monitored_var["delta"] for monitored_var in monitored_vars] +anom_factors = [monitored_var["anom_factor"] for monitored_var in monitored_vars] +thresholds = [monitored_var["threshold"] for monitored_var in monitored_vars] +available_mods = [monitored_var["available"] for monitored_var in monitored_vars] +monitored_vars = [monitored_var["monitored_var"] for monitored_var in monitored_vars] -def train_deployment_id( + +def train_deployment_id_doml_element_name( deployment_id, + doml_element_name, + doml_element_type, metric_source=metric_source, path=models_path, force=False, latest_metrics=None, ): logging.debug("training model with: {}".format(type(metric_source).__name__)) - model_path = Path(path).joinpath(deployment_id) + model_path = Path(path).joinpath(deployment_id).joinpath(doml_element_name).joinpath(doml_element_type) if not force: - model_pkl_path = model_path.joinpath("model.pkl") + model_pkl_path = model_path.joinpath("cpuUP_model.pkl") if model_pkl_path.exists(): logging.debug("Training already present for: {}".format(deployment_id)) return if latest_metrics is None: - latest_metrics = metric_source.get_latest_n_metrics( - deployment_id, training_size + latest_metrics = metric_source.get_latest_n_metrics_doml_element_name( + deployment_id, doml_element_name, doml_element_type, training_size ) if latest_metrics is None: logging.error("No metrics for: {}".format(deployment_id)) return + model_path.mkdir(parents=True, exist_ok=True) + logging.debug("Training for: {}".format(latest_metrics)) training_done = train( latest_metrics, horizon, feat_name, - lab_name, + lab_names, model_path.as_posix() + "/", - window_anom_detect, - delta, + window_anom_detects, + deltas, + available_mods=available_mods, ) if training_done: logging.debug("Successfull training") else: - logging.error("Training was not completed for: {}".format(deployment_id)) + logging.error("Training was not completed for: {}/{}/{}".format(deployment_id, doml_element_name, doml_element_type)) def predict_deployment_id( - deployment_id, metric_source=metric_source, path=models_path, latest_metrics=None + deployment_id, + doml_element_name, + doml_element_type, + metric_source=metric_source, + path=models_path, + latest_metrics=None ): - model_path = Path(path).joinpath(deployment_id) - model_pkl_path = model_path.joinpath("model.pkl") + model_path = Path(path).joinpath(deployment_id).joinpath(doml_element_name).joinpath(doml_element_type) + model_pkl_path = model_path.joinpath("cpuUP_model.pkl") if not model_pkl_path.exists(): logging.error("No model present for {}".format(deployment_id)) return if latest_metrics is None: - latest_metrics = metric_source.get_latest_metrics(deployment_id) + latest_metrics = metric_source.get_latest_metrics_doml_element_name(deployment_id, doml_element_name, doml_element_type) if latest_metrics is None: - logging.error("No metrics for: {}".format(deployment_id)) + logging.error("latest_metrics is None for: {}".format(deployment_id)) + return + if latest_metrics.empty: + logging.error("latest_metrics is empty for: {}".format(deployment_id)) return + logging.debug("predicting for: {}".format(latest_metrics)) test_X = latest_metrics[[feat_name]] - test_Y = latest_metrics[[lab_name]] + test_Y = latest_metrics.loc[:, latest_metrics.columns != feat_name] for x, y in stream.iter_pandas(test_X, test_Y): predict_result = predict( x_data_instance=x, y_data_instance=y, horizon=horizon, feat_name=feat_name, - lab_name=lab_name, + lab_names=lab_names, path_models=model_path.as_posix() + "/", - window_anom_detect=window_anom_detect, - anom_factor=anom_factor, + window_anom_detects=window_anom_detects, + anom_factors=anom_factors, plott=False, - threshold=threshold, - monitored_var=monitored_var + thres_holds=thresholds, + monitored_variables=monitored_vars, + available_mods=available_mods, ) - logging.debug("prediction for: {} is {}".format(deployment_id,predict_result)) + logging.debug("appending: {}".format(latest_metrics[feat_name].iloc[0])) + predict_result.append(str(latest_metrics[feat_name].iloc[0])) + logging.debug("prediction for: {}/{}/{} is\n{}".format(deployment_id,doml_element_name,doml_element_type, predict_result)) return predict_result diff --git a/src/psl/adapters/sh_client_to_sh_client.py b/src/psl/adapters/sh_client_to_sh_client.py index dcb1716..31153cb 100644 --- a/src/psl/adapters/sh_client_to_sh_client.py +++ b/src/psl/adapters/sh_client_to_sh_client.py @@ -17,7 +17,7 @@ sh_client_url = predictor_adapter_config["url"].get() sh_client_base64_secret = predictor_adapter_config["base64_secret"].get() sh_client_secret = base64.b64decode(sh_client_base64_secret) sh_client_verify_ssl = predictor_adapter_config["verify_ssl"].get() - +sh_client_enabled = predictor_adapter_config["enabled"].get() # https://auth0.com/blog/how-to-handle-jwt-in-python/ def getBearerToken(sh_client_secret): @@ -26,7 +26,6 @@ def getBearerToken(sh_client_secret): sh_client_bearer_token = getBearerToken(sh_client_secret) -print(sh_client_bearer_token) # Defining the host is optional and defaults to /services/shbackend # See configuration.py for a list of all supported configuration parameters. @@ -41,6 +40,8 @@ configuration.debug = True def notify_threshold_event(deployment_id): + if not sh_client_enabled: + return # Enter a context with an instance of the API client # ,"Authorization", configuration.get_api_key_with_prefix("Authorization") with sh_client.ApiClient(configuration, "Authorization", configuration.get_api_key_with_prefix("Authorization")) as api_client: diff --git a/src/psl/adapters/tmp.py b/src/psl/adapters/tmp.py deleted file mode 100644 index 52d4dc8..0000000 --- a/src/psl/adapters/tmp.py +++ /dev/null @@ -1,98 +0,0 @@ - - - - - - - - - - - -influxdb_config = config["influxdb"] -feat_name = influxdb_config["feat_name"].get() -lab_name = influxdb_config["lab_name"].get() -focus_metric = influxdb_config["focus_metric"].get() - - -def get_conn_opts_from_influxdb_config(influxdb_config): - # we configure the nested separator to one _, this may produce erros but I doubt that it will happen in this code - subview = influxdb_config["connection"] - # print('subview value retrival example: subview[\'password\']: ' + str(subview['password'].get())) - subviewItemsDict = {key: value.get() for key, value in subview.items()} - return subviewItemsDict - - -def save_prediction(prediction, deployment_id): - logging.debug("Saving predict {} for deployment {} into influxdb".format(prediction, deployment_id)) - print('save into influxdb') - query_data = { - "bucket": bucket_name, - "start": time_range, - "deployment_id": str(deployment_id), - "aggregate_sampling": aggregate_sampling, - } - query = QUERY_TEMPLATE.format(**query_data) - with InfluxDBClient(**conn_opts) as client: - try: - query_api = client.query_api() - data_frame = query_api.query_data_frame(query=query) - # the number of row multiply by each additional metric, we group by time - data_frame_grouped = data_frame.groupby("_time") - # we take the last number_of_records https://stackoverflow.com/a/52895848 - data_frame = pandas.concat( - deque(map(itemgetter(1), data_frame_grouped), maxlen=number_of_records) - ) - data_frame_grouped = data_frame.groupby("_time") - # we create a new dataframe - data_frame = pandas.DataFrame( - [ - { - **dict(values[["_field", "_value"]].values), - feat_name: pandas.to_datetime(time).replace(tzinfo=None), - } - for time, values in data_frame_grouped - ] - ) - # predictor_utils.read_piacere_data establishes the index but the next step data_reparing dissable it - # it also changes time to datetime but this is already done therefore I will skip it - # predictor_utils.data_preparing changes _time to moment ... but why here and not when creating the pandas.DataFrame? - - # this may be unecessary in next version - data_frame.rename(columns={focus_metric: lab_name}, inplace=True) - data_frame = data_frame[[lab_name, feat_name]] - - return data_frame - except Exception: - logging.error( - "accesing influxdb for deployment_id: {}".format(deployment_id) - ) - - return None - - -self.client = InfluxDBClient.from_config_file("config.ini") -[influx2] -url=http://localhost:8086 -org=my-org -token=my-token -timeout=6000 - -[tags] -id = 132-987-655 -customer = California Miner -data_center = ${env.data_center} - - -from influxdb_client import InfluxDBClient, Point -from influxdb_client .client.write_api import SYNCHRONOUS - -client = InfluxDBClient(url="http://localhost:8086", token="my-token", org="my-org") -write_api = client.write_api(write_options=SYNCHRONOUS) - -_point1 = Point("my_measurement").tag("location", "Prague").field("temperature", 25.3) -_point2 = Point("my_measurement").tag("location", "New York").field("temperature", 24.3) - -write_api.write(bucket="my-bucket", record=[_point1, _point2]) - -client.close() \ No newline at end of file diff --git a/src/psl/config.yaml b/src/psl/config.yaml index f2d1d17..ea936b0 100644 --- a/src/psl/config.yaml +++ b/src/psl/config.yaml @@ -1,7 +1,8 @@ sh_client_adapter: - url: http://sh-backend:8081 # InfluxdbToMetricSource or CSVToMetricsSource + url: http://sh-backend:8081 base64_secret: MjFhOTY5YjFiYjZjZGM0YTlhZjM1OGYwZmU2MjE1ZTJiNTNmM2Q0OTdiMDhmNDQzNjRjZWQyZDM0YmI0YjkwMGI4ZDc0ZGE0MGM3Yzg0M2U2Y2Q0ZDE4MDcwNzc4ODQyMjczOWYyODNlY2RmOTQzNGQzOTc3NDc0MDdkNjlkN2I= verify_ssl: False + enabled: False predictor_adapter: metric_source_class_name: InfluxdbToMetricSource # InfluxdbToMetricSource or CSVToMetricsSource training_size: 200 @@ -9,102 +10,56 @@ predictor_adapter: feat_name: moment models_path: data/models monitored_vars: - - monitored_var: cpu_usage_idle - lab_name: _value - threshold: 70 - window_anom_detect: 50 - anom_factor: 4.0 - delta: 0.1 #Drifts - filters: - - _measurement: cpu - - _field: usage_idle - - cpu: cpu-total - - monitored_var: cpu_usage_system - lab_name: cpu_usage_system - threshold: 70.0 - window_anom_detect: 50 - anom_factor: 4.0 - delta: 0.1 #Drifts - filters: - - _measurement: cpu - - _field: usage_system - - cpu: cpu-total - - monitored_var: cpu_usage_user - lab_name: cpu_usage_user + - monitored_var: cpu_used_percent + available: true + lab_name: cpu_used_percent threshold: 70.0 window_anom_detect: 50 anom_factor: 4.0 delta: 0.1 #Drifts - filters: - - _measurement: cpu - - _field: usage_user - - cpu: cpu-total - - monitored_var: disk_free - lab_name: disk_free - threshold: 70.0 - window_anom_detect: 50 - anom_factor: 4.0 - delta: 0.1 #Drifts - filters: - - _measurement: disk - - _field: free - - path: / - monitored_var: disk_used_percent + available: true lab_name: disk_used_percent threshold: 70.0 window_anom_detect: 50 anom_factor: 4.0 delta: 0.1 #Drifts - filters: - - _measurement: disk - - _field: used_percent - - path: / - - monitored_var: mem_free - lab_name: mem_free - threshold: 70.0 - window_anom_detect: 50 - anom_factor: 4.0 - delta: 0.1 #Drifts - filters: - - _measurement: mem - - _field: free - monitored_var: mem_used_percent + available: true lab_name: mem_used_percent threshold: 70.0 window_anom_detect: 50 anom_factor: 4.0 delta: 0.1 #Drifts - filters: - - _measurement: mem - - _field: used_percent - - monitored_var: availability - lab_name: availability + - monitored_var: system_availability_percent + available: true + lab_name: system_availability_percent threshold: 70.0 window_anom_detect: 50 anom_factor: 4.0 delta: 0.1 #Drifts - filters: [] cvs: - file_path: test_input_data/usage_idle_data.csv + file_path: test_input_data/psl_data.csv time_column_name: _time feat_name: moment lab_name: _value influxdb: connection: - url: http://pmc-influxdb:8086 + url: http://pm-influxdb:8086 org: piacere username: piacere password: piacerePassword token: piacerePassword ssl: False verify_ssl: False - train_time_range_start: -40m - predict_time_range_start: -20s + train_time_range_start: -250m # 200 x aggregate_sampling + predict_time_range_start: -30m bucket_name: bucket - aggregate_sampling: 10s + aggregate_sampling: 60s feat_name: moment lab_name: _value - focus_metric: cpu_usage_idle + measurement_name: psl + telegraf_interval: 10s repository: file: data/deployments_data # relative to execution point runner: diff --git a/src/psl/controllers/self_learning_controller.py b/src/psl/controllers/self_learning_controller.py index 94595a4..36c4a44 100644 --- a/src/psl/controllers/self_learning_controller.py +++ b/src/psl/controllers/self_learning_controller.py @@ -1,6 +1,7 @@ import connexion import six +from psl.models.deployment import Deployment # noqa: E501 from psl.models.error import Error # noqa: E501 from psl import util import psl.services.self_learning_service @@ -21,14 +22,16 @@ def deployments_deployment_iddelete(deployment_id): # noqa: E501 ) -def deployments_post(body): # noqa: E501 +def deployments_post(): # noqa: E501 """Adds a resource to be learn Adds a deployment to be supervised with SelfLearning algorithms. It requires and the identifier of the resource. The same resource identifier used by the performance self learning. The result of the addition will be an acknowledge with the indentifier of the added resource. # noqa: E501 - :param body: - :type body: str + :param deployment: + :type deployment: dict | bytes :rtype: str """ - return psl.services.self_learning_service.deployments_post(body) + if connexion.request.is_json: + deployment = Deployment.from_dict(connexion.request.get_json()) # noqa: E501 + return psl.services.self_learning_service.deployments_post(deployment) diff --git a/src/psl/flows/self_learning_flow.py b/src/psl/flows/self_learning_flow.py index 9b094e4..d7de473 100644 --- a/src/psl/flows/self_learning_flow.py +++ b/src/psl/flows/self_learning_flow.py @@ -7,10 +7,18 @@ import psl.adapters.influxdb_to_influxdb as influxdb import pandas from psl.config import config import psl.adapters.sh_client_to_sh_client as sh_client - +import time +from psl.adapters.csv_to_metric_source import CSVToMetricsSource +from psl.adapters.influxdb_to_metric_source import InfluxdbToMetricSource ENCODING = 'utf-8' predictor_adapter_config = config["predictor_adapter"] +monitored_vars = predictor_adapter_config["monitored_vars"].get() +lab_names = [monitored_var["lab_name"] for monitored_var in monitored_vars] +thresholds = [monitored_var["threshold"] for monitored_var in monitored_vars] +metric_source_class_name = predictor_adapter_config["metric_source_class_name"].get() +metric_source = globals()[metric_source_class_name]() + monitored_vars = predictor_adapter_config["monitored_vars"].get() cpu_usage_idle_monitored_var = monitored_vars[0] cpu_usage_idle_threshold = cpu_usage_idle_monitored_var["threshold"] @@ -18,24 +26,63 @@ cpu_usage_idle_threshold = cpu_usage_idle_monitored_var["threshold"] def run(): logging.info("Running Self Learning Flow") + start_time = time.time() deployments = deployments_repository.get_all() + total_deployments = len(deployments) + valid_predictions = 0 for deployment_id in deployments.keys(): deployment_id = deployment_id.decode(ENCODING) - predictor.train_deployment_id(deployment_id) - prediction = None - with warnings.catch_warnings(): - # ignore all caught warnings - warnings.filterwarnings("ignore") - prediction = predictor.predict_deployment_id(deployment_id) - is_valid_prediction = False + logging.info("Processing Deployment: {}".format(deployment_id)) + latest_metrics = metric_source.get_latest_metrics(deployment_id) + + # group latest metrics by doml_element_name + if latest_metrics is None: + logging.info("No metrics found for deployment: {}".format(deployment_id)) + continue + logging.debug("latest_metrics for deployment {}:\n{}".format(deployment_id,latest_metrics)) + latest_metrics_groupby_doml_element_name = latest_metrics.groupby(["doml_element_name", "doml_element_type", "host"]) + # iterate over each doml_element_name + for [doml_element_name, doml_element_type, host] , doml_element_name_metrics in latest_metrics_groupby_doml_element_name: + influxdb.save_input(doml_element_name_metrics, deployment_id, doml_element_name, doml_element_type, host, lab_names) + # check if doml_element_name has training model + predictor.train_deployment_id_doml_element_name(deployment_id, doml_element_name, doml_element_type) + prediction = None + with warnings.catch_warnings(): + # ignore all caught warnings + warnings.filterwarnings("ignore") + prediction = predictor.predict_deployment_id(deployment_id, doml_element_name, doml_element_type, latest_metrics=doml_element_name_metrics) + is_valid_prediction = False + try: + prediction_datetime = pandas.to_datetime(prediction[-2]).replace(tzinfo=None) + input_datetime = pandas.to_datetime(prediction[-1]).replace(tzinfo=None) + is_valid_prediction = True + valid_predictions += 1 + except Exception: + logging.info("Prediction for deployment {} is invalid".format(deployment_id)) + if is_valid_prediction: + logging.info("Prediction for deployment {} is {} note that forecast time is given at GMT".format(deployment_id, prediction)) + influxdb.save_prediction(prediction, lab_names, prediction_datetime, deployment_id, doml_element_name, doml_element_type, host, input_datetime) + logging.info("Saved at: {}".format(input_datetime)) + check_thresholds(deployment_id, doml_element_name, prediction) + total_time = time.time() - start_time + logging.info("Self Learning Flow: Valid predictions {}, total deployments {}, time {} seconds".format(valid_predictions, total_deployments, total_time)) + return valid_predictions, total_deployments, total_time + + +def check_thresholds(deployment_id, doml_element_name, prediction): + for index, lab_name in enumerate(lab_names): + thresholds_ok = True try: - prediction_datetime = pandas.to_datetime(prediction[4]).replace(tzinfo=None) - is_valid_prediction = True + value = float(prediction[index][0]) + threshold = thresholds[index] + if value < threshold: + if thresholds_ok: + message = "{} element name {}".format(deployment_id, doml_element_name) + thresholds_ok = False + message = "{}\n{} threshold {} not satisfied by value {}".format(message, lab_name, threshold, value) except Exception: - logging.info("Prediction for deployment {} is invalid".format(deployment_id)) - if is_valid_prediction: - logging.info("Prediction for deployment {} is {} note that forecast time is given at GMT".format(deployment_id, prediction)) - influxdb.save_prediction(prediction, prediction_datetime, deployment_id) - if prediction[0] < cpu_usage_idle_threshold: - logging.warning("Prediction {} lower than threshold {}".format(prediction, cpu_usage_idle_threshold)) - sh_client.notify_threshold_event(deployment_id) + None + + if not thresholds_ok: + logging.warning("Thresholds not ok for deployment {} message will be sent to sh".format(deployment_id)) + sh_client.notify_threshold_event(deployment_id) diff --git a/src/psl/models/__init__.py b/src/psl/models/__init__.py index 310be3a..02e4566 100644 --- a/src/psl/models/__init__.py +++ b/src/psl/models/__init__.py @@ -3,4 +3,5 @@ # flake8: noqa from __future__ import absolute_import # import models into model package +from psl.models.deployment import Deployment from psl.models.error import Error diff --git a/src/psl/models/deployment.py b/src/psl/models/deployment.py new file mode 100644 index 0000000..b209133 --- /dev/null +++ b/src/psl/models/deployment.py @@ -0,0 +1,66 @@ +# coding: utf-8 + +from __future__ import absolute_import +from datetime import date, datetime # noqa: F401 + +from typing import List, Dict # noqa: F401 + +from psl.models.base_model_ import Model +from psl import util + + +class Deployment(Model): + """NOTE: This class is auto generated by OpenAPI Generator (https://openapi-generator.tech). + + Do not edit the class manually. + """ + + def __init__(self, deployment_id=None): # noqa: E501 + """Deployment - a model defined in OpenAPI + + :param deployment_id: The deployment_id of this Deployment. # noqa: E501 + :type deployment_id: str + """ + self.openapi_types = { + 'deployment_id': str + } + + self.attribute_map = { + 'deployment_id': 'deployment_id' + } + + self._deployment_id = deployment_id + + @classmethod + def from_dict(cls, dikt) -> 'Deployment': + """Returns the dict as a model + + :param dikt: A dict. + :type: dict + :return: The Deployment of this Deployment. # noqa: E501 + :rtype: Deployment + """ + return util.deserialize_model(dikt, cls) + + @property + def deployment_id(self): + """Gets the deployment_id of this Deployment. + + id of the deployment # noqa: E501 + + :return: The deployment_id of this Deployment. + :rtype: str + """ + return self._deployment_id + + @deployment_id.setter + def deployment_id(self, deployment_id): + """Sets the deployment_id of this Deployment. + + id of the deployment # noqa: E501 + + :param deployment_id: The deployment_id of this Deployment. + :type deployment_id: str + """ + + self._deployment_id = deployment_id diff --git a/src/psl/openapi/openapi.yaml b/src/psl/openapi/openapi.yaml index e1b5b28..34bc023 100644 --- a/src/psl/openapi/openapi.yaml +++ b/src/psl/openapi/openapi.yaml @@ -206,8 +206,14 @@ components: schemas: Deployment: description: Deployment - example: 123e4567-e89b-12d3-a456-426614174000 - type: string + example: + deployment_id: 123e4567-e89b-12d3-a456-426614174000 + properties: + deployment_id: + description: id of the deployment + type: string + title: Deployment + type: object DeploymentID: description: Id of the deployment example: 123e4567-e89b-12d3-a456-426614174000 diff --git a/src/psl/predictor/predictor.py b/src/psl/predictor/predictor.py index f149494..e8b5c71 100644 --- a/src/psl/predictor/predictor.py +++ b/src/psl/predictor/predictor.py @@ -22,51 +22,40 @@ import traceback import warnings from datetime import timedelta -from river import linear_model as riv_linear -from river import compose -from river import datasets -from river import evaluate from river import metrics -from river import time_series -from river import tree -from river import preprocessing as prep from river import stream -from river import ensemble -from river.drift import EDDM,PageHinkley -from river import anomaly from sklearn.preprocessing import MinMaxScaler,StandardScaler from river import stats from river.drift import ADWIN -from river import utils -from river import optim -from sklearn import pipeline -from river import linear_model from river import time_series from collections import deque from river import neighbors -from river import neural_net as nn + +import numpy seed=48 -warnings.filterwarnings("ignore", category=FutureWarning) +warnings.filterwarnings('ignore') ###################### FUNCTIONS ###################### ####################################################### -def train(data,horizon,feat_name,lab_name,path_models,window_anom_detect,delta): +def train(data,horizon,feat_name,lab_names,path_models,window_anom_detects,deltas,available_mods): """ This method is called once in the monitoring phase. It receives training data[n instances], and is stored when the training phases finalizes. - :param data: pandas DataFrame with the training data. 200 instances approx. - First column '_value' with the real reading of the monitoring variable (e.g. 95.28). - Second column 'moment' (which is defined by the variable 'feat_name' of the 'predictor_config.txt' config file) with the DateTime (e.g. 2021-09-20 13:00:00) + :param data: pandas DataFrame with the training data. 200 instances approx. Columns: + ['cpu_usage_percent', 'disk_used_percent', 'mem_used_percent', 'system_availability_percent', 'moment'] + + Last column 'moment' (which is defined by the variable 'feat_name' of the 'predictor_config.txt' config file) with the DateTime (e.g. 2021-09-20 13:00:00) :param horizon: number of time steps ahead to make the prediction :param feat_name: name of the DataTime feature ('moment') - :param lab_name: name of the target feature ('_value') + :param lab_names: list of names of the target features. E.g.: ['cpu_usage_percent', 'disk_used_percent', 'mem_used_percent', 'system_availability_percent'] :param path_models: path to store and load variables, models, etc. - :param window_anom_detect: length of the window to store instances for different purposes - :param delta: value for the Drift detector + :param window_anom_detects: list with the length of the window for each monitoring variable to store instances for different purposes. E.g.: [50,50,50,50,50,50,50] + :param deltas: list with the parameters values for the Drift detector for each monitoring variable. E.g.: [0.1,0.1,0.1,0.1,0.1,0.1,0.1] + :param available_mods: list of True/False to indicate the modules that are available. E.g.: [cpu_usage_percent, disk_used_percent, mem_used_percent, system_availability_percent] --> [True,False,False,False] :return: True/False """ @@ -77,7 +66,7 @@ def train(data,horizon,feat_name,lab_name,path_models,window_anom_detect,delta): # data = piacere_utils.data_preparing(data, feat_name, time_column_name) X = pd.DataFrame(data[feat_name]) X.columns = [feat_name] - Y = data.loc[:, data.columns == lab_name] + Y = data.loc[:, data.columns != feat_name] #Scaling data scaler = MinMaxScaler() @@ -88,93 +77,380 @@ def train(data,horizon,feat_name,lab_name,path_models,window_anom_detect,delta): train_Y = Y #Model definition - model=time_series.SNARIMAX(p=0,d=0,q=0,regressor=(neighbors.KNNRegressor(n_neighbors=10,window_size=horizon))) + if available_mods[0]: + cpuUP_model=time_series.SNARIMAX(p=0,d=0,q=0,regressor=(neighbors.KNNRegressor(n_neighbors=10,window_size=horizon))) + if available_mods[1]: + memUP_model=time_series.SNARIMAX(p=0,d=0,q=0,regressor=(neighbors.KNNRegressor(n_neighbors=10,window_size=horizon))) + if available_mods[2]: + diskUP_model=time_series.SNARIMAX(p=0,d=0,q=0,regressor=(neighbors.KNNRegressor(n_neighbors=10,window_size=horizon))) + if available_mods[3]: + sysAP_model=time_series.SNARIMAX(p=0,d=0,q=0,regressor=(neighbors.KNNRegressor(n_neighbors=10,window_size=horizon))) ############# Training ######################### - observed_mean=0 - observed_std=0 + #CPU_USAGE_PERCENT + if available_mods[0]: + cpuUP_observed_mean=0 + cpuUP_observed_std=0 + cpuUP_tr_readings=deque(maxlen=window_anom_detects[0]) + #MEM_USED_PERCENT + if available_mods[1]: + memUP_observed_mean=0 + memUP_observed_std=0 + memUP_tr_readings=deque(maxlen=window_anom_detects[1]) + #DISK_USED_PERCENT + if available_mods[2]: + diskUP_observed_mean=0 + diskUP_observed_std=0 + diskUP_tr_readings=deque(maxlen=window_anom_detects[2]) + #SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + sysAP_observed_mean=0 + sysAP_observed_std=0 + sysAP_tr_readings=deque(maxlen=window_anom_detects[3]) + tr=0 - tr_readings=deque(maxlen=window_anom_detect) for xr, yr in stream.iter_pandas(train_X,train_Y): - #Datos en formato con punto - int_part = str(yr[lab_name]).split('.')[0] - dec_part = str(yr[lab_name]).split('.')[1] - new_yr = float(int_part + "." + dec_part) + ##################### CPU_USAGE_PERCENT + if available_mods[0]: + + try: + #With dot format + int_part = str(yr[lab_names[0]]).split('.')[0] + dec_part = str(yr[lab_names[0]]).split('.')[1] + new_yr = float(int_part + "." + dec_part) + + cpuUP_model = cpuUP_model.learn_one(new_yr,xr) # Learning model training + + cpuUP_tr_readings.append(new_yr) + + if tr>=window_anom_detects[0]: + cpuUP_observed_mean = np.mean(cpuUP_tr_readings) + cpuUP_observed_std = np.std(cpuUP_tr_readings) + + except: + logging.debug("The value of the target variable is not a float64. It is: " + str(type(yr[lab_names[0]]))) + + ##################### MEM_USED_PERCENT + if available_mods[1]: + + try: + #With dot format + int_part = str(yr[lab_names[1]]).split('.')[0] + dec_part = str(yr[lab_names[1]]).split('.')[1] + new_yr = float(int_part + "." + dec_part) + + memUP_model = memUP_model.learn_one(new_yr, xr) # Learning model training + + memUP_tr_readings.append(new_yr) + + if tr >= window_anom_detects[1]: + memUP_observed_mean = np.mean(memUP_tr_readings) + memUP_observed_std = np.std(memUP_tr_readings) + except: + logging.debug("The value of the target variable is not a float64. It is: " + str(type(yr[lab_names[1]]))) + + ##################### DISK_USED_PERCENT + if available_mods[2]: + + try: + #With dot format + int_part = str(yr[lab_names[2]]).split('.')[0] + dec_part = str(yr[lab_names[2]]).split('.')[1] + new_yr = float(int_part + "." + dec_part) + + diskUP_model = diskUP_model.learn_one(new_yr, xr) # Learning model training + + diskUP_tr_readings.append(new_yr) - model = model.learn_one(new_yr,xr) # Learning model training + if tr >= window_anom_detects[2]: + diskUP_observed_mean = np.mean(diskUP_tr_readings) + diskUP_observed_std = np.std(diskUP_tr_readings) + except: + logging.debug("The value of the target variable is not a float64. It is: " + str(type(yr[lab_names[2]]))) - tr_readings.append(new_yr) + ##################### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: - if tr>=window_anom_detect: - observed_mean = np.mean(tr_readings) - observed_std = np.std(tr_readings) + try: + #With dot format + int_part = str(yr[lab_names[3]]).split('.')[0] + dec_part = str(yr[lab_names[3]]).split('.')[1] + new_yr = float(int_part + "." + dec_part) + + sysAP_model = sysAP_model.learn_one(new_yr, xr) # Learning model training + + sysAP_tr_readings.append(new_yr) + + if tr >= window_anom_detects[3]: + sysAP_observed_mean = np.mean(sysAP_tr_readings) + sysAP_observed_std = np.std(sysAP_tr_readings) + except: + logging.debug("The value of the target variable is not a float64. It is: " + str(type(yr[lab_names[3]]))) tr+=1 ############# Creating variables for streaming ######################### - #Drift - drift_var = stats.Var() - drifts=[] - drift_detector = ADWIN(delta=delta) - x_sw=deque(maxlen=window_anom_detect) - y_sw=deque(maxlen=window_anom_detect) - #Performance - metric = metrics.MAE() - multi_step_preds = deque(maxlen=horizon) - #Anomalies - anomalies = [] - #For plotting - real_obs=[] - forecasts=[] - anoms_detected=[] - drifts_detected=[] - maes=[] - ############# Persistence ######################### + ##################### CPU_USAGE_PERCENT + if available_mods[0]: + #Drift + cpuUP_drift_var = stats.Var() + cpuUP_drifts=[] + cpuUP_drift_detector = ADWIN(delta=deltas[0]) + cpuUP_x_sw=deque(maxlen=window_anom_detects[0]) + cpuUP_y_sw=deque(maxlen=window_anom_detects[0]) + + #Performance + cpuUP_metric = metrics.MAE() + cpuUP_multi_step_preds = deque(maxlen=horizon) + + #Anomalies + cpuUP_anomalies = [] + + #For plotting + cpuUP_real_obs=[] + cpuUP_forecasts=[] + cpuUP_anoms_detected=[] + cpuUP_drifts_detected=[] + cpuUP_maes=[] + + ##################### MEM_USED_PERCENT + if available_mods[1]: + #Drift + memUP_drift_var = stats.Var() + memUP_drifts=[] + memUP_drift_detector = ADWIN(delta=deltas[1]) + memUP_x_sw=deque(maxlen=window_anom_detects[1]) + memUP_y_sw=deque(maxlen=window_anom_detects[1]) + + #Performance + memUP_metric = metrics.MAE() + memUP_multi_step_preds = deque(maxlen=horizon) + + #Anomalies + memUP_anomalies = [] + + #For plotting + memUP_real_obs=[] + memUP_forecasts=[] + memUP_anoms_detected=[] + memUP_drifts_detected=[] + memUP_maes=[] + + ##################### DISK_USED_PERCENT + if available_mods[2]: + #Drift + diskUP_drift_var = stats.Var() + diskUP_drifts=[] + diskUP_drift_detector = ADWIN(delta=deltas[2]) + diskUP_x_sw=deque(maxlen=window_anom_detects[2]) + diskUP_y_sw=deque(maxlen=window_anom_detects[2]) + + #Performance + diskUP_metric = metrics.MAE() + diskUP_multi_step_preds = deque(maxlen=horizon) + + #Anomalies + diskUP_anomalies = [] + + #For plotting + diskUP_real_obs=[] + diskUP_forecasts=[] + diskUP_anoms_detected=[] + diskUP_drifts_detected=[] + diskUP_maes=[] + + ##################### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + #Drift + sysAP_drift_var = stats.Var() + sysAP_drifts=[] + sysAP_drift_detector = ADWIN(delta=deltas[3]) + sysAP_x_sw=deque(maxlen=window_anom_detects[3]) + sysAP_y_sw=deque(maxlen=window_anom_detects[3]) + + #Performance + sysAP_metric = metrics.MAE() + sysAP_multi_step_preds = deque(maxlen=horizon) + + #Anomalies + sysAP_anomalies = [] + + #For plotting + sysAP_real_obs=[] + sysAP_forecasts=[] + sysAP_anoms_detected=[] + sysAP_drifts_detected=[] + sysAP_maes=[] + + ############# Persistence ################################## #Saving scaler with open(path_models+'scaler.pkl', 'wb') as f: pickle.dump(scaler, f) - #Saving model - with open(path_models+'model.pkl', 'wb') as f: - pickle.dump(model, f) - #Saving anomalies statistics - with open(path_models+'anom_stats.pkl', 'wb') as f: - anom_stats=[observed_mean,observed_std] - pickle.dump(anom_stats, f) - #Saving drift variables - with open(path_models+'drift_var.pkl', 'wb') as f: - pickle.dump(drift_var, f) - with open(path_models+'drifts.pkl', 'wb') as f: - pickle.dump(drifts, f) - with open(path_models+'drift_detector.pkl', 'wb') as f: - pickle.dump(drift_detector, f) - with open(path_models+'x_sw.pkl', 'wb') as f: - pickle.dump(x_sw, f) - with open(path_models+'y_sw.pkl', 'wb') as f: - pickle.dump(y_sw, f) - #Saving performance variable - with open(path_models+'metric.pkl', 'wb') as f: - pickle.dump(metric, f) - with open(path_models+'multi_step_preds.pkl', 'wb') as f: - pickle.dump(multi_step_preds, f) - #Saving anomalies - with open(path_models+'anomalies.pkl', 'wb') as f: - pickle.dump(anomalies, f) - #Saving plotting required variable - with open(path_models+'real_obs.pkl', 'wb') as f: - pickle.dump(real_obs, f) - with open(path_models+'forecasts.pkl', 'wb') as f: - pickle.dump(forecasts, f) - with open(path_models+'maes.pkl', 'wb') as f: - pickle.dump(maes, f) - with open(path_models+'anoms_detected.pkl', 'wb') as f: - pickle.dump(anoms_detected, f) - with open(path_models+'drifts_detected.pkl', 'wb') as f: - pickle.dump(drifts_detected, f) + + ##################### CPU_USAGE_PERCENT + if available_mods[0]: + #Saving model + with open(path_models+'cpuUP_model.pkl', 'wb') as f: + pickle.dump(cpuUP_model, f) + #Saving anomalies statistics + with open(path_models+'cpuUP_anom_stats.pkl', 'wb') as f: + cpuUP_anom_stats=[cpuUP_observed_mean,cpuUP_observed_std] + pickle.dump(cpuUP_anom_stats, f) + #Saving drift variables + with open(path_models+'cpuUP_drift_var.pkl', 'wb') as f: + pickle.dump(cpuUP_drift_var, f) + with open(path_models+'cpuUP_drifts.pkl', 'wb') as f: + pickle.dump(cpuUP_drifts, f) + with open(path_models+'cpuUP_drift_detector.pkl', 'wb') as f: + pickle.dump(cpuUP_drift_detector, f) + with open(path_models+'cpuUP_x_sw.pkl', 'wb') as f: + pickle.dump(cpuUP_x_sw, f) + with open(path_models+'cpuUP_y_sw.pkl', 'wb') as f: + pickle.dump(cpuUP_y_sw, f) + #Saving performance variable + with open(path_models+'cpuUP_metric.pkl', 'wb') as f: + pickle.dump(cpuUP_metric, f) + with open(path_models+'cpuUP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(cpuUP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'cpuUP_anomalies.pkl', 'wb') as f: + pickle.dump(cpuUP_anomalies, f) + #Saving plotting required variable + with open(path_models+'cpuUP_real_obs.pkl', 'wb') as f: + pickle.dump(cpuUP_real_obs, f) + with open(path_models+'cpuUP_forecasts.pkl', 'wb') as f: + pickle.dump(cpuUP_forecasts, f) + with open(path_models+'cpuUP_maes.pkl', 'wb') as f: + pickle.dump(cpuUP_maes, f) + with open(path_models+'cpuUP_anoms_detected.pkl', 'wb') as f: + pickle.dump(cpuUP_anoms_detected, f) + with open(path_models+'cpuUP_drifts_detected.pkl', 'wb') as f: + pickle.dump(cpuUP_drifts_detected, f) + + ##################### MEM_USED_PERCENT + if available_mods[1]: + #Saving model + with open(path_models+'memUP_model.pkl', 'wb') as f: + pickle.dump(memUP_model, f) + #Saving anomalies statistics + with open(path_models+'memUP_anom_stats.pkl', 'wb') as f: + memUP_anom_stats=[memUP_observed_mean,memUP_observed_std] + pickle.dump(memUP_anom_stats, f) + #Saving drift variables + with open(path_models+'memUP_drift_var.pkl', 'wb') as f: + pickle.dump(memUP_drift_var, f) + with open(path_models+'memUP_drifts.pkl', 'wb') as f: + pickle.dump(memUP_drifts, f) + with open(path_models+'memUP_drift_detector.pkl', 'wb') as f: + pickle.dump(memUP_drift_detector, f) + with open(path_models+'memUP_x_sw.pkl', 'wb') as f: + pickle.dump(memUP_x_sw, f) + with open(path_models+'memUP_y_sw.pkl', 'wb') as f: + pickle.dump(memUP_y_sw, f) + #Saving performance variable + with open(path_models+'memUP_metric.pkl', 'wb') as f: + pickle.dump(memUP_metric, f) + with open(path_models+'memUP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(memUP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'memUP_anomalies.pkl', 'wb') as f: + pickle.dump(memUP_anomalies, f) + #Saving plotting required variable + with open(path_models+'memUP_real_obs.pkl', 'wb') as f: + pickle.dump(memUP_real_obs, f) + with open(path_models+'memUP_forecasts.pkl', 'wb') as f: + pickle.dump(memUP_forecasts, f) + with open(path_models+'memUP_maes.pkl', 'wb') as f: + pickle.dump(memUP_maes, f) + with open(path_models+'memUP_anoms_detected.pkl', 'wb') as f: + pickle.dump(memUP_anoms_detected, f) + with open(path_models+'memUP_drifts_detected.pkl', 'wb') as f: + pickle.dump(memUP_drifts_detected, f) + + ##################### DISK_USED_PERCENT + if available_mods[2]: + #Saving model + with open(path_models+'diskUP_model.pkl', 'wb') as f: + pickle.dump(diskUP_model, f) + #Saving anomalies statistics + with open(path_models+'diskUP_anom_stats.pkl', 'wb') as f: + diskUP_anom_stats=[diskUP_observed_mean,diskUP_observed_std] + pickle.dump(diskUP_anom_stats, f) + #Saving drift variables + with open(path_models+'diskUP_drift_var.pkl', 'wb') as f: + pickle.dump(diskUP_drift_var, f) + with open(path_models+'diskUP_drifts.pkl', 'wb') as f: + pickle.dump(diskUP_drifts, f) + with open(path_models+'diskUP_drift_detector.pkl', 'wb') as f: + pickle.dump(diskUP_drift_detector, f) + with open(path_models+'diskUP_x_sw.pkl', 'wb') as f: + pickle.dump(diskUP_x_sw, f) + with open(path_models+'diskUP_y_sw.pkl', 'wb') as f: + pickle.dump(diskUP_y_sw, f) + #Saving performance variable + with open(path_models+'diskUP_metric.pkl', 'wb') as f: + pickle.dump(diskUP_metric, f) + with open(path_models+'diskUP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(diskUP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'diskUP_anomalies.pkl', 'wb') as f: + pickle.dump(diskUP_anomalies, f) + #Saving plotting required variable + with open(path_models+'diskUP_real_obs.pkl', 'wb') as f: + pickle.dump(diskUP_real_obs, f) + with open(path_models+'diskUP_forecasts.pkl', 'wb') as f: + pickle.dump(diskUP_forecasts, f) + with open(path_models+'diskUP_maes.pkl', 'wb') as f: + pickle.dump(diskUP_maes, f) + with open(path_models+'diskUP_anoms_detected.pkl', 'wb') as f: + pickle.dump(diskUP_anoms_detected, f) + with open(path_models+'diskUP_drifts_detected.pkl', 'wb') as f: + pickle.dump(diskUP_drifts_detected, f) + + ##################### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + #Saving model + with open(path_models+'sysAP_model.pkl', 'wb') as f: + pickle.dump(sysAP_model, f) + #Saving anomalies statistics + with open(path_models+'sysAP_anom_stats.pkl', 'wb') as f: + sysAP_anom_stats=[sysAP_observed_mean,sysAP_observed_std] + pickle.dump(sysAP_anom_stats, f) + #Saving drift variables + with open(path_models+'sysAP_drift_var.pkl', 'wb') as f: + pickle.dump(sysAP_drift_var, f) + with open(path_models+'sysAP_drifts.pkl', 'wb') as f: + pickle.dump(sysAP_drifts, f) + with open(path_models+'sysAP_drift_detector.pkl', 'wb') as f: + pickle.dump(sysAP_drift_detector, f) + with open(path_models+'sysAP_x_sw.pkl', 'wb') as f: + pickle.dump(sysAP_x_sw, f) + with open(path_models+'sysAP_y_sw.pkl', 'wb') as f: + pickle.dump(sysAP_y_sw, f) + #Saving performance variable + with open(path_models+'sysAP_metric.pkl', 'wb') as f: + pickle.dump(sysAP_metric, f) + with open(path_models+'sysAP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(sysAP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'sysAP_anomalies.pkl', 'wb') as f: + pickle.dump(sysAP_anomalies, f) + #Saving plotting required variable + with open(path_models+'sysAP_real_obs.pkl', 'wb') as f: + pickle.dump(sysAP_real_obs, f) + with open(path_models+'sysAP_forecasts.pkl', 'wb') as f: + pickle.dump(sysAP_forecasts, f) + with open(path_models+'sysAP_maes.pkl', 'wb') as f: + pickle.dump(sysAP_maes, f) + with open(path_models+'sysAP_anoms_detected.pkl', 'wb') as f: + pickle.dump(sysAP_anoms_detected, f) + with open(path_models+'sysAP_drifts_detected.pkl', 'wb') as f: + pickle.dump(sysAP_drifts_detected, f) return True @@ -183,25 +459,33 @@ def train(data,horizon,feat_name,lab_name,path_models,window_anom_detect,delta): traceback.print_exc() return False -def predict(x_data_instance,y_data_instance,horizon,feat_name,lab_name,path_models,window_anom_detect,anom_factor,plott,threshold,monitored_var): +def predict(x_data_instance,y_data_instance,horizon,feat_name,lab_names,path_models,window_anom_detects,anom_factors,plott,thres_holds,monitored_variables,available_mods): """ This method is called every time a new incoming data instance arrives in the monitoring phase. So we have to follow a test-then-train approach, where the model makes a prediction first, and afterwards learns the data instance. :param x_data_instance: a dictionary, e.g. {'moment': numpy.datetime64('2021-11-17T14:00:00.000000000')} with the time step of the current data instance - :param y_data_instance: a dictionary e.g. {'_value': 95.86} with the usage_idle current value. + :param y_data_instance: a dictionary with the current values of each monitoring variables. E.g.: {'cpu_usage_percent': 87.70834514071545, 'disk_used_percent': 3.0945516432548805, 'mem_used_percent': 8.929829751345423, 'system_availability_percent': 25.81267896446586} :param horizon: number of time steps ahead to make the prediction :param feat_name: name of the DataTime feature ('moment') - :param lab_name: name of the target feature ('_value') + :param lab_names: list of names of the target features. E.g.: ['cpu_usage_percent', 'disk_used_percent', 'mem_used_percent', 'system_availability_percent'] :param path_models: path to store and load variables, models, etc. - :param window_anom_detect: length of the window to store instances for different purposes - :param anom_factor: factor to detect anomalies + :param window_anom_detects: list with the lengths of the window to store instances for different purposes for each monitoring variable. E.g.: [50,50,50,50,50,50,50] + :param anom_factors: factor to detect anomalies. E.g.: [4.0,4.0,4.0,4.0,4.0,4.0,4.0] :param plott: True/False to have an overall view of the process until this time step - :param threshold: the value to be plotted as frontier for the monitored variable - :param monitored_var: variable to monitor (e.g. 'cpu_usage_idle') - - :return: output:[prediction,mae,anomaly True/False,drift True/False,time of the prediction] + :param thres_holds: list of values to be plotted as frontier for the monitored variables. E.g: [70,10,70,70,10,70,10] + :param monitored_variables: list of variables to monitor. E.g.: ['cpu_usage_percent', 'disk_used_percent', 'mem_used_percent', 'system_availability_percent', 'moment'] + :param available_mods: list of True/False to indicate the modules that are available. E.g.: [cpu_usage_percent, disk_used_percent, mem_used_percent, system_availability_percent] --> [True,False,False,True] + + :return: output: list of lists (results per monitored variable) + moment. E.g.: + [ + [prediction,mae,anomaly True/False,drift True/False,time of the prediction],-->cpu_usage_percent + [prediction,mae,anomaly True/False,drift True/False,time of the prediction],-->disk_used_percent + [prediction,mae,anomaly True/False,drift True/False,time of the prediction],-->mem_used_percent + [prediction,mae,anomaly True/False,drift True/False,time of the prediction],-->system_availability_percent + ,moment of the prediction + ] """ try: @@ -211,72 +495,275 @@ def predict(x_data_instance,y_data_instance,horizon,feat_name,lab_name,path_mode #Loading scaler with open(path_models+'scaler.pkl', 'rb') as f: scaler = pickle.load(f) - #Loading model - with open(path_models+'model.pkl', 'rb') as f: - model = pickle.load(f) - #Loading anomalies statistics - with open(path_models+'anom_stats.pkl', 'rb') as f: - anom_stats = pickle.load(f) - #Loading drift variables - with open(path_models+'drift_var.pkl', 'rb') as f: - drift_var = pickle.load(f) - with open(path_models+'drifts.pkl', 'rb') as f: - drifts = pickle.load(f) - with open(path_models+'drift_detector.pkl', 'rb') as f: - drift_detector = pickle.load(f) - with open(path_models+'drift_detector.pkl', 'rb') as f: - drift_detector = pickle.load(f) - with open(path_models+'x_sw.pkl', 'rb') as f: - x_sw = pickle.load(f) - with open(path_models+'y_sw.pkl', 'rb') as f: - y_sw = pickle.load(f) - #Loading performance variable - with open(path_models+'metric.pkl', 'rb') as f: - metric = pickle.load(f) - with open(path_models+'multi_step_preds.pkl', 'rb') as f: - multi_step_preds = pickle.load(f) - #Loading anomalies - with open(path_models+'anomalies.pkl', 'rb') as f: - anomalies = pickle.load(f) - - # Loading persisted variables required for plotting - # Real observations until this moment - with open(path_models + 'real_obs.pkl', 'rb') as f: - real_obs = pickle.load(f) - # Predictions until this moment - with open(path_models + 'forecasts.pkl', 'rb') as f: - forecasts = pickle.load(f) - # Mean Absolute Error (MAE) until this moment - with open(path_models + 'maes.pkl', 'rb') as f: - maes = pickle.load(f) - # Drifts detected until this moment - with open(path_models + 'drifts_detected.pkl', 'rb') as f: - drifts_detected = pickle.load(f) - # Anomalies detected until this moment - with open(path_models + 'anoms_detected.pkl', 'rb') as f: - anoms_detected = pickle.load(f) - - #Local Variables - observed_mean=anom_stats[0] - observed_std=anom_stats[1] - anom=False - drft=False + + ##################### CPU_USAGE_PERCENT + if available_mods[0]: + #Loading model + with open(path_models+'cpuUP_model.pkl', 'rb') as f: + cpuUP_model = pickle.load(f) + #Loading anomalies statistics + with open(path_models+'cpuUP_anom_stats.pkl', 'rb') as f: + cpuUP_anom_stats = pickle.load(f) + #Loading drift variables + with open(path_models+'cpuUP_drift_var.pkl', 'rb') as f: + cpuUP_drift_var = pickle.load(f) + with open(path_models+'cpuUP_drifts.pkl', 'rb') as f: + cpuUP_drifts = pickle.load(f) + with open(path_models+'cpuUP_drift_detector.pkl', 'rb') as f: + cpuUP_drift_detector = pickle.load(f) + with open(path_models+'cpuUP_x_sw.pkl', 'rb') as f: + cpuUP_x_sw = pickle.load(f) + with open(path_models+'cpuUP_y_sw.pkl', 'rb') as f: + cpuUP_y_sw = pickle.load(f) + #Loading performance variable + with open(path_models+'cpuUP_metric.pkl', 'rb') as f: + cpuUP_metric = pickle.load(f) + with open(path_models+'cpuUP_multi_step_preds.pkl', 'rb') as f: + cpuUP_multi_step_preds = pickle.load(f) + #Loading anomalies + with open(path_models+'cpuUP_anomalies.pkl', 'rb') as f: + cpuUP_anomalies = pickle.load(f) + + # Loading persisted variables required for plotting + # Real observations until this moment + with open(path_models + 'cpuUP_real_obs.pkl', 'rb') as f: + cpuUP_real_obs = pickle.load(f) + # Predictions until this moment + with open(path_models + 'cpuUP_forecasts.pkl', 'rb') as f: + cpuUP_forecasts = pickle.load(f) + # Mean Absolute Error (MAE) until this moment + with open(path_models + 'cpuUP_maes.pkl', 'rb') as f: + cpuUP_maes = pickle.load(f) + # Drifts detected until this moment + with open(path_models + 'cpuUP_drifts_detected.pkl', 'rb') as f: + cpuUP_drifts_detected = pickle.load(f) + # Anomalies detected until this moment + with open(path_models + 'cpuUP_anoms_detected.pkl', 'rb') as f: + cpuUP_anoms_detected = pickle.load(f) + + #Local Variables + cpuUP_observed_mean=cpuUP_anom_stats[0] + cpuUP_observed_std=cpuUP_anom_stats[1] + cpuUP_anom=False + cpuUP_drft=False + + ##################### MEM_USED_PERCENT + if available_mods[1]: + #Loading model + with open(path_models+'memUP_model.pkl', 'rb') as f: + memUP_model = pickle.load(f) + #Loading anomalies statistics + with open(path_models+'memUP_anom_stats.pkl', 'rb') as f: + memUP_anom_stats = pickle.load(f) + #Loading drift variables + with open(path_models+'memUP_drift_var.pkl', 'rb') as f: + memUP_drift_var = pickle.load(f) + with open(path_models+'memUP_drifts.pkl', 'rb') as f: + memUP_drifts = pickle.load(f) + with open(path_models+'memUP_drift_detector.pkl', 'rb') as f: + memUP_drift_detector = pickle.load(f) + with open(path_models+'memUP_x_sw.pkl', 'rb') as f: + memUP_x_sw = pickle.load(f) + with open(path_models+'memUP_y_sw.pkl', 'rb') as f: + memUP_y_sw = pickle.load(f) + #Loading performance variable + with open(path_models+'memUP_metric.pkl', 'rb') as f: + memUP_metric = pickle.load(f) + with open(path_models+'memUP_multi_step_preds.pkl', 'rb') as f: + memUP_multi_step_preds = pickle.load(f) + #Loading anomalies + with open(path_models+'memUP_anomalies.pkl', 'rb') as f: + memUP_anomalies = pickle.load(f) + + # Loading persisted variables required for plotting + # Real observations until this moment + with open(path_models + 'memUP_real_obs.pkl', 'rb') as f: + memUP_real_obs = pickle.load(f) + # Predictions until this moment + with open(path_models + 'memUP_forecasts.pkl', 'rb') as f: + memUP_forecasts = pickle.load(f) + # Mean Absolute Error (MAE) until this moment + with open(path_models + 'memUP_maes.pkl', 'rb') as f: + memUP_maes = pickle.load(f) + # Drifts detected until this moment + with open(path_models + 'memUP_drifts_detected.pkl', 'rb') as f: + memUP_drifts_detected = pickle.load(f) + # Anomalies detected until this moment + with open(path_models + 'memUP_anoms_detected.pkl', 'rb') as f: + memUP_anoms_detected = pickle.load(f) + + #Local Variables + memUP_observed_mean=memUP_anom_stats[0] + memUP_observed_std=memUP_anom_stats[1] + memUP_anom=False + memUP_drft=False + + ##################### DISK_USED_PERCENT + if available_mods[2]: + #Loading model + with open(path_models+'diskUP_model.pkl', 'rb') as f: + diskUP_model = pickle.load(f) + #Loading anomalies statistics + with open(path_models+'diskUP_anom_stats.pkl', 'rb') as f: + diskUP_anom_stats = pickle.load(f) + #Loading drift variables + with open(path_models+'diskUP_drift_var.pkl', 'rb') as f: + diskUP_drift_var = pickle.load(f) + with open(path_models+'diskUP_drifts.pkl', 'rb') as f: + diskUP_drifts = pickle.load(f) + with open(path_models+'diskUP_drift_detector.pkl', 'rb') as f: + diskUP_drift_detector = pickle.load(f) + with open(path_models+'diskUP_x_sw.pkl', 'rb') as f: + diskUP_x_sw = pickle.load(f) + with open(path_models+'diskUP_y_sw.pkl', 'rb') as f: + diskUP_y_sw = pickle.load(f) + #Loading performance variable + with open(path_models+'diskUP_metric.pkl', 'rb') as f: + diskUP_metric = pickle.load(f) + with open(path_models+'diskUP_multi_step_preds.pkl', 'rb') as f: + diskUP_multi_step_preds = pickle.load(f) + #Loading anomalies + with open(path_models+'diskUP_anomalies.pkl', 'rb') as f: + diskUP_anomalies = pickle.load(f) + + # Loading persisted variables required for plotting + # Real observations until this moment + with open(path_models + 'diskUP_real_obs.pkl', 'rb') as f: + diskUP_real_obs = pickle.load(f) + # Predictions until this moment + with open(path_models + 'diskUP_forecasts.pkl', 'rb') as f: + diskUP_forecasts = pickle.load(f) + # Mean Absolute Error (MAE) until this moment + with open(path_models + 'diskUP_maes.pkl', 'rb') as f: + diskUP_maes = pickle.load(f) + # Drifts detected until this moment + with open(path_models + 'diskUP_drifts_detected.pkl', 'rb') as f: + diskUP_drifts_detected = pickle.load(f) + # Anomalies detected until this moment + with open(path_models + 'diskUP_anoms_detected.pkl', 'rb') as f: + diskUP_anoms_detected = pickle.load(f) + + #Local Variables + diskUP_observed_mean=diskUP_anom_stats[0] + diskUP_observed_std=diskUP_anom_stats[1] + diskUP_anom=False + diskUP_drft=False + + ##################### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + #Loading model + with open(path_models+'sysAP_model.pkl', 'rb') as f: + sysAP_model = pickle.load(f) + #Loading anomalies statistics + with open(path_models+'sysAP_anom_stats.pkl', 'rb') as f: + sysAP_anom_stats = pickle.load(f) + #Loading drift variables + with open(path_models+'sysAP_drift_var.pkl', 'rb') as f: + sysAP_drift_var = pickle.load(f) + with open(path_models+'sysAP_drifts.pkl', 'rb') as f: + sysAP_drifts = pickle.load(f) + with open(path_models+'sysAP_drift_detector.pkl', 'rb') as f: + sysAP_drift_detector = pickle.load(f) + with open(path_models+'sysAP_x_sw.pkl', 'rb') as f: + sysAP_x_sw = pickle.load(f) + with open(path_models+'sysAP_y_sw.pkl', 'rb') as f: + sysAP_y_sw = pickle.load(f) + #Loading performance variable + with open(path_models+'sysAP_metric.pkl', 'rb') as f: + sysAP_metric = pickle.load(f) + with open(path_models+'sysAP_multi_step_preds.pkl', 'rb') as f: + sysAP_multi_step_preds = pickle.load(f) + #Loading anomalies + with open(path_models+'sysAP_anomalies.pkl', 'rb') as f: + sysAP_anomalies = pickle.load(f) + + # Loading persisted variables required for plotting + # Real observations until this moment + with open(path_models + 'sysAP_real_obs.pkl', 'rb') as f: + sysAP_real_obs = pickle.load(f) + # Predictions until this moment + with open(path_models + 'sysAP_forecasts.pkl', 'rb') as f: + sysAP_forecasts = pickle.load(f) + # Mean Absolute Error (MAE) until this moment + with open(path_models + 'sysAP_maes.pkl', 'rb') as f: + sysAP_maes = pickle.load(f) + # Drifts detected until this moment + with open(path_models + 'sysAP_drifts_detected.pkl', 'rb') as f: + sysAP_drifts_detected = pickle.load(f) + # Anomalies detected until this moment + with open(path_models + 'sysAP_anoms_detected.pkl', 'rb') as f: + sysAP_anoms_detected = pickle.load(f) + + #Local Variables + sysAP_observed_mean=sysAP_anom_stats[0] + sysAP_observed_std=sysAP_anom_stats[1] + sysAP_anom=False + sysAP_drft=False ############# Data Transformation ######################### #X transf_x = scaler.transform([[x_data_instance[feat_name]]])[0] x_dict = {feat_name: transf_x[0]} - #Y - int_part = str(y_data_instance[lab_name]).split('.')[0] - dec_part = str(y_data_instance[lab_name]).split('.')[1] - new_y = float(int_part + "." + dec_part) - real_obs.append(new_y) - - x_sw.append(x_dict) - y_sw.append(new_y) + #Y - ############# PREDICTING t + horizon ######################### + if available_mods[0]: + #### CPU_USAGE_PERCENT + try: + cpuUP_int_part = str(y_data_instance[lab_names[0]]).split('.')[0] + cpuUP_dec_part = str(y_data_instance[lab_names[0]]).split('.')[1] + cpuUP_new_y = float(cpuUP_int_part + "." + cpuUP_dec_part) + + cpuUP_real_obs.append(cpuUP_new_y) + + cpuUP_x_sw.append(x_dict) + cpuUP_y_sw.append(cpuUP_new_y) + except: + logging.debug("The value of the target variable {} cannot be transformed: {}".format(lab_names[0], y_data_instance[lab_names[0]])) + + if available_mods[1]: + #### MEM_USED_PERCENT + try: + memUP_int_part = str(y_data_instance[lab_names[1]]).split('.')[0] + memUP_dec_part = str(y_data_instance[lab_names[1]]).split('.')[1] + memUP_new_y = float(memUP_int_part + "." + memUP_dec_part) + + memUP_real_obs.append(memUP_new_y) + + memUP_x_sw.append(x_dict) + memUP_y_sw.append(memUP_new_y) + except: + logging.debug("The value of the target variable {} cannot be transformed: {}".format(lab_names[1], y_data_instance[lab_names[1]])) + + if available_mods[2]: + #### DISK_USED_PERCENT + try: + diskUP_int_part = str(y_data_instance[lab_names[2]]).split('.')[0] + diskUP_dec_part = str(y_data_instance[lab_names[2]]).split('.')[1] + diskUP_new_y = float(diskUP_int_part + "." + diskUP_dec_part) + + diskUP_real_obs.append(diskUP_new_y) + + diskUP_x_sw.append(x_dict) + diskUP_y_sw.append(diskUP_new_y) + except: + logging.debug("The value of the target variable {} cannot be transformed: {}".format(lab_names[2], y_data_instance[lab_names[2]])) + + if available_mods[3]: + #### SYSTEM_AVAILABILITY_PERCENT + try: + sysAP_int_part = str(y_data_instance[lab_names[3]]).split('.')[0] + sysAP_dec_part = str(y_data_instance[lab_names[3]]).split('.')[1] + sysAP_new_y = float(sysAP_int_part + "." + sysAP_dec_part) + + sysAP_real_obs.append(sysAP_new_y) + + sysAP_x_sw.append(x_dict) + sysAP_y_sw.append(sysAP_new_y) + except: + logging.debug("The value of the target variable {} cannot be transformed: {}".format(lab_names[3], y_data_instance[lab_names[3]])) + + ############# PREDICTING t + horizon ##################################################### future = [] df_x = pd.DataFrame.from_dict(x_data_instance, orient='index', columns=[feat_name]) @@ -289,125 +776,501 @@ def predict(x_data_instance,y_data_instance,horizon,feat_name,lab_name,path_mode fut_x_dict = {feat_name: scaler.transform([df_x.iloc[[0]][feat_name]])[0]} future.append(fut_x_dict) - y_pred = model.forecast(horizon=horizon, xs=future)[-1] # Predictions for the next [horizon] time steps. We take the last one because it its the one that we need - multi_step_preds.append(y_pred) - forecasts.append(y_pred) - - ############# VALIDATING ######################### - if len(multi_step_preds)==horizon: - metric = metric.update(new_y, multi_step_preds[0]) - maes.append(metric.get()) + #### CPU_USAGE_PERCENT + if available_mods[0]: + cpuUP_y_pred = cpuUP_model.forecast(horizon=horizon, xs=future)[-1] # Predictions for the next [horizon] time steps. We take the last one because it its the one that we need + cpuUP_multi_step_preds.append(cpuUP_y_pred) + cpuUP_forecasts.append(cpuUP_y_pred) + #### MEM_USED_PERCENT + if available_mods[1]: + memUP_y_pred = memUP_model.forecast(horizon=horizon, xs=future)[-1] # Predictions for the next [horizon] time steps. We take the last one because it its the one that we need + memUP_multi_step_preds.append(memUP_y_pred) + memUP_forecasts.append(memUP_y_pred) + #### DISK_USED_PERCENT + if available_mods[2]: + diskUP_y_pred = diskUP_model.forecast(horizon=horizon, xs=future)[-1] # Predictions for the next [horizon] time steps. We take the last one because it its the one that we need + diskUP_multi_step_preds.append(diskUP_y_pred) + diskUP_forecasts.append(diskUP_y_pred) + #### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + sysAP_y_pred = sysAP_model.forecast(horizon=horizon, xs=future)[-1] # Predictions for the next [horizon] time steps. We take the last one because it its the one that we need + sysAP_multi_step_preds.append(sysAP_y_pred) + sysAP_forecasts.append(sysAP_y_pred) + + ############# VALIDATING ##################################################### + #### CPU_USAGE_PERCENT + if available_mods[0]: + try: + if len(cpuUP_multi_step_preds)==horizon: + cpuUP_metric = cpuUP_metric.update(cpuUP_new_y, cpuUP_multi_step_preds[0]) + cpuUP_maes.append(cpuUP_metric.get()) + except: + logging.debug("The value of the target variable {} is not valid: {}".format(lab_names[0], y_data_instance[lab_names[0]])) + #### MEM_USED_PERCENT + if available_mods[1]: + try: + if len(memUP_multi_step_preds)==horizon: + memUP_metric = memUP_metric.update(memUP_new_y, memUP_multi_step_preds[0]) + memUP_maes.append(memUP_metric.get()) + except: + logging.debug("The value of the target variable {} is not valid: {}".format(lab_names[1], y_data_instance[lab_names[1]])) + #### DISK_USED_PERCENT + if available_mods[2]: + try: + if len(diskUP_multi_step_preds)==horizon: + diskUP_metric = diskUP_metric.update(diskUP_new_y, diskUP_multi_step_preds[0]) + diskUP_maes.append(diskUP_metric.get()) + except: + logging.debug("The value of the target variable {} is not valid: {}".format(lab_names[2], y_data_instance[lab_names[2]])) + #### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + try: + if len(sysAP_multi_step_preds)==horizon: + sysAP_metric = sysAP_metric.update(sysAP_new_y, sysAP_multi_step_preds[0]) + sysAP_maes.append(sysAP_metric.get()) + except: + logging.debug("The value of the target variable {} is not valid: {}".format(lab_names[3], y_data_instance[lab_names[3]])) ############# TRAINING/LEARNING ######################### - if len(y_sw) >= window_anom_detect: - - observed_mean = np.mean(y_sw) - observed_std = np.std(y_sw) - - #Anomalies treatment - if new_y > observed_mean + (anom_factor * observed_std) or new_y < observed_mean - (anom_factor * observed_std): - logging.info('Anomaly detected at t %s',str(x_data_instance[feat_name])) - anomalies.append(str(x_data_instance[feat_name])) - anom=True - anoms_detected.append(1) - else: - model = model.learn_one(new_y, x_dict) - anoms_detected.append(0) - else: - model = model.learn_one(new_y, x_dict) - anoms_detected.append(0) + #### CPU_USAGE_PERCENT + if available_mods[0]: + try: + if len(cpuUP_y_sw) >= window_anom_detects[0]: + + cpuUP_observed_mean = np.mean(cpuUP_y_sw) + cpuUP_observed_std = np.std(cpuUP_y_sw) + + #Anomalies treatment + if cpuUP_new_y > cpuUP_observed_mean + (anom_factors[0] * cpuUP_observed_std) or cpuUP_new_y < cpuUP_observed_mean - (anom_factors[0] * cpuUP_observed_std): + logging.info('CPU_USAGE_PERCENT: Anomaly detected at t %s',str(x_data_instance[feat_name])) + cpuUP_anomalies.append(str(x_data_instance[feat_name])) + cpuUP_anom=True + cpuUP_anoms_detected.append(1) + else: + cpuUP_model = cpuUP_model.learn_one(cpuUP_new_y, x_dict) + cpuUP_anoms_detected.append(0) + else: + cpuUP_model = cpuUP_model.learn_one(cpuUP_new_y, x_dict) + cpuUP_anoms_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot train/learning: {}".format(lab_names[0], y_data_instance[lab_names[0]])) + + #### MEM_USED_PERCENT + if available_mods[1]: + try: + if len(memUP_y_sw) >= window_anom_detects[1]: + + memUP_observed_mean = np.mean(memUP_y_sw) + memUP_observed_std = np.std(memUP_y_sw) + + #Anomalies treatment + if memUP_new_y > memUP_observed_mean + (anom_factors[1] * memUP_observed_std) or memUP_new_y < memUP_observed_mean - (anom_factors[1] * memUP_observed_std): + logging.info('MEM_USED_PERCENT: Anomaly detected at t %s',str(x_data_instance[feat_name])) + memUP_anomalies.append(str(x_data_instance[feat_name])) + memUP_anom=True + memUP_anoms_detected.append(1) + else: + memUP_model = memUP_model.learn_one(memUP_new_y, x_dict) + memUP_anoms_detected.append(0) + else: + memUP_model = memUP_model.learn_one(memUP_new_y, x_dict) + memUP_anoms_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot train/learning: {}".format(lab_names[1], y_data_instance[lab_names[1]])) + + #### DISK_USED_PERCENT + if available_mods[2]: + try: + if len(diskUP_y_sw) >= window_anom_detects[2]: + + diskUP_observed_mean = np.mean(diskUP_y_sw) + diskUP_observed_std = np.std(diskUP_y_sw) + + #Anomalies treatment + if diskUP_new_y > diskUP_observed_mean + (anom_factors[2] * diskUP_observed_std) or diskUP_new_y < diskUP_observed_mean - (anom_factors[2] * diskUP_observed_std): + logging.info('DISK USED_PERCENT: Anomaly detected at t %s',str(x_data_instance[feat_name])) + diskUP_anomalies.append(str(x_data_instance[feat_name])) + diskUP_anom=True + diskUP_anoms_detected.append(1) + else: + diskUP_model = diskUP_model.learn_one(diskUP_new_y, x_dict) + diskUP_anoms_detected.append(0) + else: + diskUP_model = diskUP_model.learn_one(diskUP_new_y, x_dict) + diskUP_anoms_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot train/learning: {}".format(lab_names[2], y_data_instance[lab_names[2]])) + + #### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + try: + if len(sysAP_y_sw) >= window_anom_detects[3]: + + sysAP_observed_mean = np.mean(sysAP_y_sw) + sysAP_observed_std = np.std(sysAP_y_sw) + + #Anomalies treatment + if sysAP_new_y > sysAP_observed_mean + (anom_factors[3] * sysAP_observed_std) or sysAP_new_y < sysAP_observed_mean - (anom_factors[3] * sysAP_observed_std): + logging.info('SYSTEM_AVAILABILITY_PERCENT: Anomaly detected at t %s',str(x_data_instance[feat_name])) + sysAP_anomalies.append(str(x_data_instance[feat_name])) + sysAP_anom=True + sysAP_anoms_detected.append(1) + else: + sysAP_model = sysAP_model.learn_one(sysAP_new_y, x_dict) + sysAP_anoms_detected.append(0) + else: + sysAP_model = sysAP_model.learn_one(sysAP_new_y, x_dict) + sysAP_anoms_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot train/learning: {}".format(lab_names[3], y_data_instance[lab_names[3]])) ############# DRIFT DETECTION ######################### - dif = new_y - multi_step_preds[0] - drift_var.update(dif) - sd = math.sqrt(drift_var.get()) - - # if drift_var.mean.n == 1: - # input_drift_detector = 0.5 # The expected error is the normalized mean error - - input_drift_detector = 0 - if sd > 0: - input_drift_detector = (dif + 3 * sd) / (6 * sd) - else: - input_drift_detector = 0.5 - - drift_detector.update(input_drift_detector) - - if drift_detector.change_detected: - logging.info('Drift detected at t %s', str(x_data_instance[feat_name])) - drifts.append(str(x_data_instance[feat_name])) - drft=True - - # Reset detector - drift_detector.reset() - drift_var = stats.Var() - - # Retrain the model with the latest instances - model = model.clone() - for h in range(0, window_anom_detect): - model = model.learn_one(y_sw[h], x_sw[h]) # Training with sliding window - - drifts_detected.append(1) - else: - drifts_detected.append(0) - + #### CPU_USAGE_PERCENT + if available_mods[0]: + try: + cpuUP_dif = cpuUP_new_y - cpuUP_multi_step_preds[0] + cpuUP_drift_var.update(cpuUP_dif) + cpuUP_sd = math.sqrt(cpuUP_drift_var.get()) + + # if drift_var.mean.n == 1: + # input_drift_detector = 0.5 # The expected error is the normalized mean error + + input_drift_detector = 0 + if cpuUP_sd > 0: + cpuUP_input_drift_detector = (cpuUP_dif + 3 * cpuUP_sd) / (6 * cpuUP_sd) + else: + cpuUP_input_drift_detector = 0.5 + + cpuUP_drift_detector.update(cpuUP_input_drift_detector) + + if cpuUP_drift_detector.change_detected: + logging.info('CPU_USAGE_PERCENT: Drift detected at t %s', str(x_data_instance[feat_name])) + cpuUP_drifts.append(str(x_data_instance[feat_name])) + cpuUP_drft=True + + # Reset detector + cpuUP_drift_detector.reset() + cpuUP_drift_var = stats.Var() + + # Retrain the model with the latest instances + cpuUP_model = cpuUP_model.clone() + for h in range(len(cpuUP_y_sw)): + cpuUP_model = cpuUP_model.learn_one(cpuUP_y_sw[h], cpuUP_x_sw[h]) # Training with sliding window + + cpuUP_drifts_detected.append(1) + else: + cpuUP_drifts_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot drift: {}".format(lab_names[0], y_data_instance[lab_names[0]])) + + #### MEM_USED_PERCENT + if available_mods[1]: + try: + memUP_dif = memUP_new_y - memUP_multi_step_preds[0] + memUP_drift_var.update(memUP_dif) + memUP_sd = math.sqrt(memUP_drift_var.get()) + + # if drift_var.mean.n == 1: + # input_drift_detector = 0.5 # The expected error is the normalized mean error + + input_drift_detector = 0 + if memUP_sd > 0: + memUP_input_drift_detector = (memUP_dif + 3 * memUP_sd) / (6 * memUP_sd) + else: + memUP_input_drift_detector = 0.5 + + memUP_drift_detector.update(memUP_input_drift_detector) + + if memUP_drift_detector.change_detected: + logging.info('MEM_USED_PERCENT: Drift detected at t %s', str(x_data_instance[feat_name])) + memUP_drifts.append(str(x_data_instance[feat_name])) + memUP_drft=True + + # Reset detector + memUP_drift_detector.reset() + memUP_drift_var = stats.Var() + + # Retrain the model with the latest instances + memUP_model = memUP_model.clone() + for h in range(len(memUP_y_sw)): + memUP_model = memUP_model.learn_one(memUP_y_sw[h], memUP_x_sw[h]) # Training with sliding window + + memUP_drifts_detected.append(1) + else: + memUP_drifts_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot drift: {}".format(lab_names[1], y_data_instance[lab_names[1]])) + + #### DISK_USED_PERCENT + if available_mods[2]: + try: + diskUP_dif = diskUP_new_y - diskUP_multi_step_preds[0] + diskUP_drift_var.update(diskUP_dif) + diskUP_sd = math.sqrt(diskUP_drift_var.get()) + + # if drift_var.mean.n == 1: + # input_drift_detector = 0.5 # The expected error is the normalized mean error + + input_drift_detector = 0 + if diskUP_sd > 0: + diskUP_input_drift_detector = (diskUP_dif + 3 * diskUP_sd) / (6 * diskUP_sd) + else: + diskUP_input_drift_detector = 0.5 + + diskUP_drift_detector.update(diskUP_input_drift_detector) + + if diskUP_drift_detector.change_detected: + logging.info('DISK USED PERCENT: Drift detected at t %s', str(x_data_instance[feat_name])) + diskUP_drifts.append(str(x_data_instance[feat_name])) + diskUP_drft=True + + # Reset detector + diskUP_drift_detector.reset() + diskUP_drift_var = stats.Var() + + # Retrain the model with the latest instances + diskUP_model = diskUP_model.clone() + for h in range(len(diskUP_y_sw)): + diskUP_model = diskUP_model.learn_one(diskUP_y_sw[h], diskUP_x_sw[h]) # Training with sliding window + + diskUP_drifts_detected.append(1) + else: + diskUP_drifts_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot drift: {}".format(lab_names[2], y_data_instance[lab_names[2]])) + + #### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + try: + sysAP_dif = sysAP_new_y - sysAP_multi_step_preds[0] + sysAP_drift_var.update(sysAP_dif) + sysAP_sd = math.sqrt(sysAP_drift_var.get()) + + # if drift_var.mean.n == 1: + # input_drift_detector = 0.5 # The expected error is the normalized mean error + + input_drift_detector = 0 + if sysAP_sd > 0: + sysAP_input_drift_detector = (sysAP_dif + 3 * sysAP_sd) / (6 * sysAP_sd) + else: + sysAP_input_drift_detector = 0.5 + + sysAP_drift_detector.update(sysAP_input_drift_detector) + + if sysAP_drift_detector.change_detected: + logging.info('SYSTEM_AVAILABILITY_PERCENT: Drift detected at t %s', str(x_data_instance[feat_name])) + sysAP_drifts.append(str(x_data_instance[feat_name])) + sysAP_drft=True + + # Reset detector + sysAP_drift_detector.reset() + sysAP_drift_var = stats.Var() + + # Retrain the model with the latest instances + sysAP_model = sysAP_model.clone() + for h in range(len(sysAP_y_sw)): + sysAP_model = sysAP_model.learn_one(sysAP_y_sw[h], sysAP_x_sw[h]) # Training with sliding window + + sysAP_drifts_detected.append(1) + else: + sysAP_drifts_detected.append(0) + except: + logging.debug("The value of the target variable {} cannot drift: {}".format(lab_names[3], y_data_instance[lab_names[3]])) ############# Persistence ######################### - #Saving model - with open(path_models+'model.pkl', 'wb') as f: - pickle.dump(model, f) - #Saving anomalies statistics - with open(path_models+'anom_stats.pkl', 'wb') as f: - anom_stats=[observed_mean,observed_std] - pickle.dump(anom_stats, f) - #Saving drift variables - with open(path_models+'drift_var.pkl', 'wb') as f: - pickle.dump(drift_var, f) - with open(path_models+'drifts.pkl', 'wb') as f: - pickle.dump(drifts, f) - with open(path_models+'drift_detector.pkl', 'wb') as f: - pickle.dump(drift_detector, f) - with open(path_models+'x_sw.pkl', 'wb') as f: - pickle.dump(x_sw, f) - with open(path_models+'y_sw.pkl', 'wb') as f: - pickle.dump(y_sw, f) - #Saving performance variable - with open(path_models+'metric.pkl', 'wb') as f: - pickle.dump(metric, f) - with open(path_models+'multi_step_preds.pkl', 'wb') as f: - pickle.dump(multi_step_preds, f) - #Saving anomalies - with open(path_models+'anomalies.pkl', 'wb') as f: - pickle.dump(anomalies, f) - #Saving information for plotting - with open(path_models+'real_obs.pkl', 'wb') as f: - pickle.dump(real_obs, f) - with open(path_models+'forecasts.pkl', 'wb') as f: - pickle.dump(forecasts, f) - with open(path_models+'maes.pkl', 'wb') as f: - pickle.dump(maes, f) - with open(path_models+'anoms_detected.pkl', 'wb') as f: - pickle.dump(anoms_detected, f) - with open(path_models+'drifts_detected.pkl', 'wb') as f: - pickle.dump(drifts_detected, f) - - if plott: - predictor_utils.plot_integration_results(path_models,threshold,monitored_var) + #### CPU_USAGE_PERCENT + if available_mods[0]: + #Saving model + with open(path_models+'cpuUP_model.pkl', 'wb') as f: + pickle.dump(cpuUP_model, f) + #Saving anomalies statistics + with open(path_models+'cpuUP_anom_stats.pkl', 'wb') as f: + cpuUP_anom_stats=[cpuUP_observed_mean,cpuUP_observed_std] + pickle.dump(cpuUP_anom_stats, f) + #Saving drift variables + with open(path_models+'cpuUP_drift_var.pkl', 'wb') as f: + pickle.dump(cpuUP_drift_var, f) + with open(path_models+'cpuUP_drifts.pkl', 'wb') as f: + pickle.dump(cpuUP_drifts, f) + with open(path_models+'cpuUP_drift_detector.pkl', 'wb') as f: + pickle.dump(cpuUP_drift_detector, f) + with open(path_models+'cpuUP_x_sw.pkl', 'wb') as f: + pickle.dump(cpuUP_x_sw, f) + with open(path_models+'cpuUP_y_sw.pkl', 'wb') as f: + pickle.dump(cpuUP_y_sw, f) + #Saving performance variable + with open(path_models+'cpuUP_metric.pkl', 'wb') as f: + pickle.dump(cpuUP_metric, f) + with open(path_models+'cpuUP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(cpuUP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'cpuUP_anomalies.pkl', 'wb') as f: + pickle.dump(cpuUP_anomalies, f) + #Saving information for plotting + with open(path_models+'cpuUP_real_obs.pkl', 'wb') as f: + pickle.dump(cpuUP_real_obs, f) + with open(path_models+'cpuUP_forecasts.pkl', 'wb') as f: + pickle.dump(cpuUP_forecasts, f) + with open(path_models+'cpuUP_maes.pkl', 'wb') as f: + pickle.dump(cpuUP_maes, f) + with open(path_models+'cpuUP_anoms_detected.pkl', 'wb') as f: + pickle.dump(cpuUP_anoms_detected, f) + with open(path_models+'cpuUP_drifts_detected.pkl', 'wb') as f: + pickle.dump(cpuUP_drifts_detected, f) + + #### MEM_USED_PERCENT + if available_mods[1]: + #Saving model + with open(path_models+'memUP_model.pkl', 'wb') as f: + pickle.dump(memUP_model, f) + #Saving anomalies statistics + with open(path_models+'memUP_anom_stats.pkl', 'wb') as f: + memUP_anom_stats=[memUP_observed_mean,memUP_observed_std] + pickle.dump(memUP_anom_stats, f) + #Saving drift variables + with open(path_models+'memUP_drift_var.pkl', 'wb') as f: + pickle.dump(memUP_drift_var, f) + with open(path_models+'memUP_drifts.pkl', 'wb') as f: + pickle.dump(memUP_drifts, f) + with open(path_models+'memUP_drift_detector.pkl', 'wb') as f: + pickle.dump(memUP_drift_detector, f) + with open(path_models+'memUP_x_sw.pkl', 'wb') as f: + pickle.dump(memUP_x_sw, f) + with open(path_models+'memUP_y_sw.pkl', 'wb') as f: + pickle.dump(memUP_y_sw, f) + #Saving performance variable + with open(path_models+'memUP_metric.pkl', 'wb') as f: + pickle.dump(memUP_metric, f) + with open(path_models+'memUP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(memUP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'memUP_anomalies.pkl', 'wb') as f: + pickle.dump(memUP_anomalies, f) + #Saving information for plotting + with open(path_models+'memUP_real_obs.pkl', 'wb') as f: + pickle.dump(memUP_real_obs, f) + with open(path_models+'memUP_forecasts.pkl', 'wb') as f: + pickle.dump(memUP_forecasts, f) + with open(path_models+'memUP_maes.pkl', 'wb') as f: + pickle.dump(memUP_maes, f) + with open(path_models+'memUP_anoms_detected.pkl', 'wb') as f: + pickle.dump(memUP_anoms_detected, f) + with open(path_models+'memUP_drifts_detected.pkl', 'wb') as f: + pickle.dump(memUP_drifts_detected, f) + + #### DISK USED_PERCENT + if available_mods[2]: + #Saving model + with open(path_models+'diskUP_model.pkl', 'wb') as f: + pickle.dump(diskUP_model, f) + #Saving anomalies statistics + with open(path_models+'diskUP_anom_stats.pkl', 'wb') as f: + diskUP_anom_stats=[diskUP_observed_mean,diskUP_observed_std] + pickle.dump(diskUP_anom_stats, f) + #Saving drift variables + with open(path_models+'diskUP_drift_var.pkl', 'wb') as f: + pickle.dump(diskUP_drift_var, f) + with open(path_models+'diskUP_drifts.pkl', 'wb') as f: + pickle.dump(diskUP_drifts, f) + with open(path_models+'diskUP_drift_detector.pkl', 'wb') as f: + pickle.dump(diskUP_drift_detector, f) + with open(path_models+'diskUP_x_sw.pkl', 'wb') as f: + pickle.dump(diskUP_x_sw, f) + with open(path_models+'diskUP_y_sw.pkl', 'wb') as f: + pickle.dump(diskUP_y_sw, f) + #Saving performance variable + with open(path_models+'diskUP_metric.pkl', 'wb') as f: + pickle.dump(diskUP_metric, f) + with open(path_models+'diskUP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(diskUP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'diskUP_anomalies.pkl', 'wb') as f: + pickle.dump(diskUP_anomalies, f) + #Saving information for plotting + with open(path_models+'diskUP_real_obs.pkl', 'wb') as f: + pickle.dump(diskUP_real_obs, f) + with open(path_models+'diskUP_forecasts.pkl', 'wb') as f: + pickle.dump(diskUP_forecasts, f) + with open(path_models+'diskUP_maes.pkl', 'wb') as f: + pickle.dump(diskUP_maes, f) + with open(path_models+'diskUP_anoms_detected.pkl', 'wb') as f: + pickle.dump(diskUP_anoms_detected, f) + with open(path_models+'diskUP_drifts_detected.pkl', 'wb') as f: + pickle.dump(diskUP_drifts_detected, f) + + #### SYSTEM_AVAILABILITY_PERCENT + if available_mods[3]: + #Saving model + with open(path_models+'sysAP_model.pkl', 'wb') as f: + pickle.dump(sysAP_model, f) + #Saving anomalies statistics + with open(path_models+'sysAP_anom_stats.pkl', 'wb') as f: + sysAP_anom_stats=[sysAP_observed_mean,sysAP_observed_std] + pickle.dump(sysAP_anom_stats, f) + #Saving drift variables + with open(path_models+'sysAP_drift_var.pkl', 'wb') as f: + pickle.dump(sysAP_drift_var, f) + with open(path_models+'sysAP_drifts.pkl', 'wb') as f: + pickle.dump(sysAP_drifts, f) + with open(path_models+'sysAP_drift_detector.pkl', 'wb') as f: + pickle.dump(sysAP_drift_detector, f) + with open(path_models+'sysAP_x_sw.pkl', 'wb') as f: + pickle.dump(sysAP_x_sw, f) + with open(path_models+'sysAP_y_sw.pkl', 'wb') as f: + pickle.dump(sysAP_y_sw, f) + #Saving performance variable + with open(path_models+'sysAP_metric.pkl', 'wb') as f: + pickle.dump(sysAP_metric, f) + with open(path_models+'sysAP_multi_step_preds.pkl', 'wb') as f: + pickle.dump(sysAP_multi_step_preds, f) + #Saving anomalies + with open(path_models+'sysAP_anomalies.pkl', 'wb') as f: + pickle.dump(sysAP_anomalies, f) + #Saving information for plotting + with open(path_models+'sysAP_real_obs.pkl', 'wb') as f: + pickle.dump(sysAP_real_obs, f) + with open(path_models+'sysAP_forecasts.pkl', 'wb') as f: + pickle.dump(sysAP_forecasts, f) + with open(path_models+'sysAP_maes.pkl', 'wb') as f: + pickle.dump(sysAP_maes, f) + with open(path_models+'sysAP_anoms_detected.pkl', 'wb') as f: + pickle.dump(sysAP_anoms_detected, f) + with open(path_models+'sysAP_drifts_detected.pkl', 'wb') as f: + pickle.dump(sysAP_drifts_detected, f) - output=[np.round(y_pred,2),np.round(metric.get(),2),anom,drft,future_t]#[prediction,mae,anomalies,drifts,future_t] + if plott: + predictor_utils.plot_integration_results(path_models,thres_holds,monitored_variables) + + #OUTPUT + # output=[[np.round(cpuUP_y_pred,2),np.round(cpuUP_metric.get(),2),cpuUP_anom,cpuUP_drft], + # [np.round(sysAP_y_pred, 2), np.round(sysAP_metric.get(), 2), sysAP_anom, sysAP_drft], + # [np.round(cpuUU_y_pred, 2), np.round(cpuUU_metric.get(), 2), cpuUU_anom, cpuUU_drft], + # future_t] + + output=[] + if available_mods[0]: + output.append([np.round(cpuUP_y_pred, 2), np.round(cpuUP_metric.get(), 2), cpuUP_anom, cpuUP_drft]) + if available_mods[1]: + output.append([np.round(memUP_y_pred, 2), np.round(memUP_metric.get(), 2), memUP_anom, memUP_drft]) + if available_mods[2]: + output.append([np.round(diskUP_y_pred, 2), np.round(diskUP_metric.get(), 2), diskUP_anom, diskUP_drft]) + if available_mods[3]: + output.append([np.round(sysAP_y_pred, 2), np.round(sysAP_metric.get(), 2), sysAP_anom, sysAP_drft]) + + output.append(future_t) return output except: logging.error('It seems that the prediction process has raised an error.') traceback.print_exc() - output=[0,0,False,False,'No future time'] + output=[0,0,0,False,False,False,'No future time'] return output ###################### MAIN ###################################### -# Gorka's monitoring simulation: USAGE_IDLE monitoring variable +# Gorka's monitoring simulation ################################################################## @@ -420,19 +1283,19 @@ if __name__ == "__main__": path=config.get('Global', 'path') time_column_nam = config.get('Global', 'time_column_name') feat_nam = config.get('Global', 'feat_name') - lab_nam = config.get('Global', 'lab_name') n_tr_instances = int(config.get('Global', 'n_training_instances')) horiz = int(config.get('Global', 'horizon'))#Number of time steps ahead to make the prediction (10) path_mods=config.get('Global', 'path_models') log_level=config.get('Global', 'log_level') - cpu_usage_idle=config.get('Global', 'cpu_usage_idle') - cpu_usage_system=config.get('Global', 'cpu_usage_system') - cpu_usage_user=config.get('Global', 'cpu_usage_user') - mem_free=config.get('Global', 'mem_free') - mem_used_percent=config.get('Global', 'mem_used_percent') - disk_free=config.get('Global', 'disk_free') - disk_used_percent=config.get('Global', 'disk_used_percent') + file_nam = config.get('Global', 'file_name') + + cpu_usage_percent=predictor_utils.to_bool(config.get('Global', 'cpu_usage_percent')) + mem_used_percent=predictor_utils.to_bool(config.get('Global', 'mem_used_percent')) + disk_used_percent=predictor_utils.to_bool(config.get('Global', 'disk_used_percent')) + system_availability_percent=predictor_utils.to_bool(config.get('Global', 'system_availability_percent')) + + available_modules=[cpu_usage_percent,mem_used_percent,disk_used_percent,system_availability_percent] if log_level=='DEBUG': logging.basicConfig(level=logging.DEBUG) @@ -445,59 +1308,105 @@ if __name__ == "__main__": elif log_level=='INFO': logging.basicConfig(level=logging.INFO) - #CPU_USAGE_IDLE - if cpu_usage_idle: - cpuUI_w_anom_detect = int(config.get('CPU-usage_idle', 'window_anom_detect')) - cpuUI_delta = float(config.get('CPU-usage_idle', 'delta')) - cpuUI_file_nam=config.get('CPU-usage_idle', 'file_name') - cpuUI_anom_fact = float(config.get('CPU-usage_idle', 'anom_factor')) - threshold = float(config.get('CPU-usage_idle', 'threshold')) - monitored_var = config.get('CPU-usage_idle', 'monitored_var') - ''' - #CPU_USAGE_SYSTEM - cpuUS_w_anom_detect = int(config.get('CPU-usage_system', 'window_anom_detect')) - cpuUS_delta = float(config.get('CPU-usage_system', 'delta')) - cpuUS_file_nam=config.get('CPU-usage_system', 'file_name') - #CPU_USAGE_USER - cpuUU_w_anom_detect = int(config.get('CPU-usage_user', 'window_anom_detect')) - cpuUU_delta = float(config.get('CPU-usage_user', 'delta')) - cpuUU_file_nam=config.get('CPU-usage_user', 'file_name') - #MEM_FREE - memF_w_anom_detect = int(config.get('MEM-free', 'window_anom_detect')) - memF_delta = float(config.get('MEM-free', 'delta')) - memF_file_nam=config.get('MEM-free', 'file_name') + w_anom_detects=[] + deltas=[] + file_nams=[] + anom_facts=[] + thresholds=[] + monitored_vars=[] + lab_nams=[] + + #CPU_USAGE_PERCENT + cpuUP_w_anom_detect = int(config.get('CPU-usage_percent', 'window_anom_detect')) + w_anom_detects.append(cpuUP_w_anom_detect) + + cpuUP_delta = float(config.get('CPU-usage_percent', 'delta')) + deltas.append(cpuUP_delta) + + cpuUP_anom_fact = float(config.get('CPU-usage_percent', 'anom_factor')) + anom_facts.append(cpuUP_anom_fact) + + cpuUP_threshold = float(config.get('CPU-usage_percent', 'threshold')) + thresholds.append(cpuUP_threshold) + + cpuUP_monitored_var = config.get('CPU-usage_percent', 'monitored_var') + monitored_vars.append(cpuUP_monitored_var) + + cpuUP_lab_nam = config.get('CPU-usage_percent', 'lab_name') + lab_nams.append(cpuUP_lab_nam) + #MEM_USED_PERCENT memUP_w_anom_detect = int(config.get('MEM-used_percent', 'window_anom_detect')) + w_anom_detects.append(memUP_w_anom_detect) + memUP_delta = float(config.get('MEM-used_percent', 'delta')) - memUP_file_nam=config.get('MEM-used_percent', 'file_name') - #DISK_FREE - diskF_w_anom_detect = int(config.get('DISK-free', 'window_anom_detect')) - diskF_delta = float(config.get('DISK-free', 'delta')) - diskF_file_nam=config.get('DISK-free', 'file_name') + deltas.append(memUP_delta) + + memUP_anom_fact = float(config.get('MEM-used_percent', 'anom_factor')) + anom_facts.append(memUP_anom_fact) + + memUP_threshold = float(config.get('MEM-used_percent', 'threshold')) + thresholds.append(memUP_threshold) + + memUP_monitored_var = config.get('MEM-used_percent', 'monitored_var') + monitored_vars.append(memUP_monitored_var) + + memUP_lab_nam = config.get('MEM-used_percent', 'lab_name') + lab_nams.append(memUP_lab_nam) + #DISK_USED_PERCENT diskUP_w_anom_detect = int(config.get('DISK-used_percent', 'window_anom_detect')) + w_anom_detects.append(diskUP_w_anom_detect) + diskUP_delta = float(config.get('DISK-used_percent', 'delta')) - diskUP_file_nam=config.get('DISK-used_percent', 'file_name') - #AVAILABILITY] - aval_w_anom_detect = int(config.get('AVAILABILITY', 'window_anom_detect')) - aval_delta = float(config.get('AVAILABILITY', 'delta')) - aval_file_nam=config.get('AVAILABILITY', 'file_name') - ''' - #CPU_USAGE_IDLE Data simulation - data=predictor_utils.read_piacere_data(path,cpuUI_file_nam,time_column_nam) + deltas.append(diskUP_delta) + + diskUP_anom_fact = float(config.get('DISK-used_percent', 'anom_factor')) + anom_facts.append(diskUP_anom_fact) + + diskUP_threshold = float(config.get('DISK-used_percent', 'threshold')) + thresholds.append(diskUP_threshold) + + diskUP_monitored_var = config.get('DISK-used_percent', 'monitored_var') + monitored_vars.append(diskUP_monitored_var) + + diskUP_lab_nam = config.get('DISK-used_percent', 'lab_name') + lab_nams.append(diskUP_lab_nam) + + #SYSTEM_AVAILABILITY_PERCENT + sysAP_w_anom_detect = int(config.get('SYSTEM-availability-percent', 'window_anom_detect')) + w_anom_detects.append(sysAP_w_anom_detect) + + sysAP_delta = float(config.get('SYSTEM-availability-percent', 'delta')) + deltas.append(sysAP_delta) + + sysAP_anom_fact = float(config.get('SYSTEM-availability-percent', 'anom_factor')) + anom_facts.append(sysAP_anom_fact) + + sysAP_threshold = float(config.get('SYSTEM-availability-percent', 'threshold')) + thresholds.append(sysAP_threshold) + + sysAP_monitored_var = config.get('SYSTEM-availability-percent', 'monitored_var') + monitored_vars.append(sysAP_monitored_var) + + sysAP_lab_nam = config.get('SYSTEM-availability-percent', 'lab_name') + lab_nams.append(sysAP_lab_nam) + #Data simulation + data=predictor_utils.read_piacere_data(path,file_nam,time_column_nam) data=predictor_utils.data_preparing(data,feat_nam,time_column_nam) + train_data=data[0:n_tr_instances] test_data=data[n_tr_instances:] - #CPU_USAGE_IDLE Training - tr_done=train(train_data,horiz,feat_nam,lab_nam,path_mods,cpuUI_w_anom_detect,cpuUI_delta) + #Training + tr_done=train(train_data,horiz,feat_nam,lab_nams,path_mods,w_anom_detects,deltas,available_modules) if tr_done: logging.info('Successfull training') - #CPU_USAGE_IDLE Testing/Predicting + #Testing/Predicting test_X = test_data[[feat_nam]] test_X=test_X[n_tr_instances:] - test_Y = test_data.loc[:, test_data.columns == lab_nam] + test_Y = test_data.loc[:, test_data.columns != feat_nam] test_Y = test_Y[n_tr_instances:] cont=0 @@ -507,7 +1416,7 @@ if __name__ == "__main__": if cont==test_X.shape[0]-1:#Plot is generated at the end of the process, but can be passed 'plotting=True' when necessary, e.g. every day plotting = True - usage_idle_out=predict(x,y,horiz,feat_nam,lab_nam,path_mods,cpuUI_w_anom_detect,cpuUI_anom_fact,plotting,threshold,monitored_var) + out=predict(x,y,horiz,feat_nam,lab_nams,path_mods,w_anom_detects,anom_facts,plotting,thresholds,monitored_vars,available_modules) logging.info(str(x[feat_nam])) - logging.info(usage_idle_out) + logging.info(out) cont+=1 diff --git a/src/psl/predictor/predictor_config.txt b/src/psl/predictor/predictor_config.txt index 152592c..8066937 100644 --- a/src/psl/predictor/predictor_config.txt +++ b/src/psl/predictor/predictor_config.txt @@ -1,25 +1,25 @@ [Global] -path=C:\\Users\\106811\\PycharmProjects\\ml-for-ds\\data\\ +path=C:\\Users\\106811\\PycharmProjects\\psl\\test_input_data\\ +file_name=psl_data.csv path_models=C:\\Users\\106811\\PycharmProjects\\ml-for-ds\\models\\ n_training_instances=200 horizon=10 -lab_name=_value time_column_name=_time feat_name=moment log_level=INFO cpu_usage_idle=True -cpu_usage_system=False -cpu_usage_user=False -mem_free=False -mem_used_percent=False -disk_free=False -disk_used_percent=False +cpu_usage_system=True +cpu_usage_user=True +mem_free=True +mem_used_percent=True +disk_free=True +disk_used_percent=True [CPU-usage_idle] -file_name=2021-11-24-09-36_usage_idle_data.csv threshold=70.0 +lab_name=cpu_usage_idle monitored_var=cpu_usage_idle #Anomalies window_anom_detect=50 @@ -29,14 +29,68 @@ delta=0.1 [CPU-usage_system] +threshold=10.0 +lab_name=cpu_usage_system +monitored_var=cpu_usage_system +#Anomalies +window_anom_detect=50 +anom_factor=4.0 +#Drifts +delta=0.1 + [CPU-usage_user] +threshold=10.0 +lab_name=cpu_usage_user +monitored_var=cpu_usage_user +#Anomalies +window_anom_detect=50 +anom_factor=4.0 +#Drifts +delta=0.1 + [MEM-free] +threshold=10.0 +lab_name=mem_free +monitored_var=mem_free +#Anomalies +window_anom_detect=50 +anom_factor=4.0 +#Drifts +delta=0.1 + [MEM-used_percent] +threshold=10.0 +lab_name=mem_used_percent +monitored_var=mem_used_percent +#Anomalies +window_anom_detect=50 +anom_factor=4.0 +#Drifts +delta=0.1 + [DISK-free] +threshold=10.0 +lab_name=disk_free +monitored_var=disk_free +#Anomalies +window_anom_detect=50 +anom_factor=4.0 +#Drifts +delta=0.1 + [DISK-used_percent] +threshold=10.0 +lab_name=disk_used_percent +monitored_var=disk_used_percent +#Anomalies +window_anom_detect=50 +anom_factor=4.0 +#Drifts +delta=0.1 + [AVAILABILITY] diff --git a/src/psl/predictor/predictor_utils.py b/src/psl/predictor/predictor_utils.py index 09bae1d..45459aa 100644 --- a/src/psl/predictor/predictor_utils.py +++ b/src/psl/predictor/predictor_utils.py @@ -140,54 +140,344 @@ def data_preparing(dat,f_name,t_name): # # plt.savefig(path_out+lab_name) -def plot_integration_results(path_models,th,name): +def plot_integration_results(path_models,ths,names): #Loading persisted variables required for plotting + + #################################################### CPU_USAGE_IDLE + + #Real observations until this moment + with open(path_models + 'cpuUI_real_obs.pkl', 'rb') as f: + cpuUI_real_obs = pickle.load(f) + #Predictions until this moment + with open(path_models + 'cpuUI_forecasts.pkl', 'rb') as f: + cpuUI_forecasts = pickle.load(f) + #Mean Absolute Error (MAE) until this moment + with open(path_models + 'cpuUI_maes.pkl', 'rb') as f: + cpuUI_maes = pickle.load(f) + #Drifts detected until this moment + with open(path_models + 'cpuUI_drifts_detected.pkl', 'rb') as f: + cpuUI_drifts_detected = pickle.load(f) + #Anomalies detected until this moment + with open(path_models + 'cpuUI_anoms_detected.pkl', 'rb') as f: + cpuUI_anoms_detected = pickle.load(f) + + # Plot the results + fig, ax = plt.subplots(figsize=(10, 6)) + ax.grid(alpha=0.75) + ax.plot(cpuUI_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(cpuUI_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + + ax.plot(np.zeros(len(cpuUI_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(cpuUI_drifts_detected)): + if cpuUI_drifts_detected[d]==1: + ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') + + ax.plot(np.zeros(len(cpuUI_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(cpuUI_anoms_detected)): + if cpuUI_anoms_detected[a]==1: + ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') + + # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') + ax.axhline(ths[0], lw=1, color='red', alpha=0.8,linestyle='--') + + ax.legend(loc='lower right') + cpuUI_res=np.round(np.nanmean(cpuUI_maes),3) + cpuUI_std_res=np.round(np.nanstd(cpuUI_maes),3) + ax.set_title('CPU_USAGE_IDLE - MAE+-std: '+str(cpuUI_res)+' +- '+str(cpuUI_std_res)) + plt.show() + + print('CPU_USAGE_IDLE - MAE+-std: '+str(cpuUI_res)+' +- '+str(cpuUI_std_res)) + + plt.savefig(path_models+names[0]+'.png') + + #################################################### CPU_USAGE_SYSTEM + + #Real observations until this moment + with open(path_models + 'cpuUS_real_obs.pkl', 'rb') as f: + cpuUS_real_obs = pickle.load(f) + #Predictions until this moment + with open(path_models + 'cpuUS_forecasts.pkl', 'rb') as f: + cpuUS_forecasts = pickle.load(f) + #Mean Absolute Error (MAE) until this moment + with open(path_models + 'cpuUS_maes.pkl', 'rb') as f: + cpuUS_maes = pickle.load(f) + #Drifts detected until this moment + with open(path_models + 'cpuUS_drifts_detected.pkl', 'rb') as f: + cpuUS_drifts_detected = pickle.load(f) + #Anomalies detected until this moment + with open(path_models + 'cpuUS_anoms_detected.pkl', 'rb') as f: + cpuUS_anoms_detected = pickle.load(f) + + + # Plot the results + fig, ax = plt.subplots(figsize=(10, 6)) + ax.grid(alpha=0.75) + ax.plot(cpuUS_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(cpuUS_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + + ax.plot(np.zeros(len(cpuUS_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(cpuUS_drifts_detected)): + if cpuUS_drifts_detected[d]==1: + ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') + + ax.plot(np.zeros(len(cpuUS_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(cpuUS_anoms_detected)): + if cpuUS_anoms_detected[a]==1: + ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') + + # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') + ax.axhline(ths[1], lw=1, color='red', alpha=0.8,linestyle='--') + + ax.legend(loc='lower right') + cpuUS_res=np.round(np.nanmean(cpuUS_maes),3) + cpuUS_std_res=np.round(np.nanstd(cpuUS_maes),3) + ax.set_title('CPU_USAGE_SYSTEM - MAE+-std: '+str(cpuUS_res)+' +- '+str(cpuUS_std_res)) + plt.show() + + print('CPU_USAGE_SYSTEM - MAE+-std: '+str(cpuUS_res)+' +- '+str(cpuUS_std_res)) + + plt.savefig(path_models+names[1]+'.png') + + #################################################### CPU_USAGE_USER + + #Real observations until this moment + with open(path_models + 'cpuUU_real_obs.pkl', 'rb') as f: + cpuUU_real_obs = pickle.load(f) + #Predictions until this moment + with open(path_models + 'cpuUU_forecasts.pkl', 'rb') as f: + cpuUU_forecasts = pickle.load(f) + #Mean Absolute Error (MAE) until this moment + with open(path_models + 'cpuUU_maes.pkl', 'rb') as f: + cpuUU_maes = pickle.load(f) + #Drifts detected until this moment + with open(path_models + 'cpuUU_drifts_detected.pkl', 'rb') as f: + cpuUU_drifts_detected = pickle.load(f) + #Anomalies detected until this moment + with open(path_models + 'cpuUU_anoms_detected.pkl', 'rb') as f: + cpuUU_anoms_detected = pickle.load(f) + + + # Plot the results + fig, ax = plt.subplots(figsize=(10, 6)) + ax.grid(alpha=0.75) + ax.plot(cpuUU_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(cpuUU_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + + ax.plot(np.zeros(len(cpuUU_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(cpuUU_drifts_detected)): + if cpuUU_drifts_detected[d]==1: + ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') + + ax.plot(np.zeros(len(cpuUU_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(cpuUU_anoms_detected)): + if cpuUU_anoms_detected[a]==1: + ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') + + # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') + ax.axhline(ths[2], lw=1, color='red', alpha=0.8,linestyle='--') + + ax.legend(loc='lower right') + cpuUU_res=np.round(np.nanmean(cpuUU_maes),3) + cpuUU_std_res=np.round(np.nanstd(cpuUU_maes),3) + ax.set_title('CPU_USAGE_USER - MAE+-std: '+str(cpuUU_res)+' +- '+str(cpuUU_std_res)) + plt.show() + + print('CPU_USAGE_USER - MAE+-std: '+str(cpuUU_res)+' +- '+str(cpuUU_std_res)) + + plt.savefig(path_models+names[2]+'.png') + + #################################################### MEM_FREE + + #Real observations until this moment + with open(path_models + 'memF_real_obs.pkl', 'rb') as f: + memF_real_obs = pickle.load(f) + #Predictions until this moment + with open(path_models + 'memF_forecasts.pkl', 'rb') as f: + memF_forecasts = pickle.load(f) + #Mean Absolute Error (MAE) until this moment + with open(path_models + 'memF_maes.pkl', 'rb') as f: + memF_maes = pickle.load(f) + #Drifts detected until this moment + with open(path_models + 'memF_drifts_detected.pkl', 'rb') as f: + memF_drifts_detected = pickle.load(f) + #Anomalies detected until this moment + with open(path_models + 'memF_anoms_detected.pkl', 'rb') as f: + memF_anoms_detected = pickle.load(f) + + + # Plot the results + fig, ax = plt.subplots(figsize=(10, 6)) + ax.grid(alpha=0.75) + ax.plot(memF_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(memF_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + + ax.plot(np.zeros(len(memF_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(memF_drifts_detected)): + if memF_drifts_detected[d]==1: + ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') + + ax.plot(np.zeros(len(memF_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(memF_anoms_detected)): + if memF_anoms_detected[a]==1: + ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') + + # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') + ax.axhline(ths[3], lw=1, color='red', alpha=0.8,linestyle='--') + + ax.legend(loc='lower right') + memF_res=np.round(np.nanmean(memF_maes),3) + memF_std_res=np.round(np.nanstd(memF_maes),3) + ax.set_title('MEM FREE - MAE+-std: '+str(memF_res)+' +- '+str(memF_std_res)) + plt.show() + + print('MEM FREE - MAE+-std: '+str(memF_res)+' +- '+str(memF_std_res)) + + plt.savefig(path_models+names[3]+'.png') + + #################################################### MEM_USED_PERCENT + + #Real observations until this moment + with open(path_models + 'memUP_real_obs.pkl', 'rb') as f: + memUP_real_obs = pickle.load(f) + #Predictions until this moment + with open(path_models + 'memUP_forecasts.pkl', 'rb') as f: + memUP_forecasts = pickle.load(f) + #Mean Absolute Error (MAE) until this moment + with open(path_models + 'memUP_maes.pkl', 'rb') as f: + memUP_maes = pickle.load(f) + #Drifts detected until this moment + with open(path_models + 'memUP_drifts_detected.pkl', 'rb') as f: + memUP_drifts_detected = pickle.load(f) + #Anomalies detected until this moment + with open(path_models + 'memUP_anoms_detected.pkl', 'rb') as f: + memUP_anoms_detected = pickle.load(f) + + + # Plot the results + fig, ax = plt.subplots(figsize=(10, 6)) + ax.grid(alpha=0.75) + ax.plot(memUP_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(memUP_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + + ax.plot(np.zeros(len(memUP_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(memUP_drifts_detected)): + if memUP_drifts_detected[d]==1: + ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') + + ax.plot(np.zeros(len(memUP_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(memUP_anoms_detected)): + if memUP_anoms_detected[a]==1: + ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') + + # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') + ax.axhline(ths[4], lw=1, color='red', alpha=0.8,linestyle='--') + + ax.legend(loc='lower right') + memUP_res=np.round(np.nanmean(memUP_maes),3) + memUP_std_res=np.round(np.nanstd(memUP_maes),3) + ax.set_title('MEM USED_PERCENT - MAE+-std: '+str(memUP_res)+' +- '+str(memUP_std_res)) + plt.show() + + print('MEM USED_PERCENT - MAE+-std: '+str(memUP_res)+' +- '+str(memUP_std_res)) + + plt.savefig(path_models+names[4]+'.png') + + #################################################### DISK_FREE + + #Real observations until this moment + with open(path_models + 'diskF_real_obs.pkl', 'rb') as f: + diskF_real_obs = pickle.load(f) + #Predictions until this moment + with open(path_models + 'diskF_forecasts.pkl', 'rb') as f: + diskF_forecasts = pickle.load(f) + #Mean Absolute Error (MAE) until this moment + with open(path_models + 'diskF_maes.pkl', 'rb') as f: + diskF_maes = pickle.load(f) + #Drifts detected until this moment + with open(path_models + 'diskF_drifts_detected.pkl', 'rb') as f: + diskF_drifts_detected = pickle.load(f) + #Anomalies detected until this moment + with open(path_models + 'diskF_anoms_detected.pkl', 'rb') as f: + diskF_anoms_detected = pickle.load(f) + + + # Plot the results + fig, ax = plt.subplots(figsize=(10, 6)) + ax.grid(alpha=0.75) + ax.plot(diskF_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(diskF_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + + ax.plot(np.zeros(len(diskF_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(diskF_drifts_detected)): + if diskF_drifts_detected[d]==1: + ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') + + ax.plot(np.zeros(len(diskF_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(diskF_anoms_detected)): + if diskF_anoms_detected[a]==1: + ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') + + # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') + ax.axhline(ths[5], lw=1, color='red', alpha=0.8,linestyle='--') + + ax.legend(loc='lower right') + diskF_res=np.round(np.nanmean(diskF_maes),3) + diskF_std_res=np.round(np.nanstd(diskF_maes),3) + ax.set_title('DISK FREE - MAE+-std: '+str(diskF_res)+' +- '+str(diskF_std_res)) + plt.show() + + print('DISK FREE - MAE+-std: '+str(diskF_res)+' +- '+str(diskF_std_res)) + + plt.savefig(path_models+names[5]+'.png') + + #################################################### DISK_USED_PERCENT + #Real observations until this moment - with open(path_models + 'real_obs.pkl', 'rb') as f: - real_obs = pickle.load(f) + with open(path_models + 'diskUP_real_obs.pkl', 'rb') as f: + diskUP_real_obs = pickle.load(f) #Predictions until this moment - with open(path_models + 'forecasts.pkl', 'rb') as f: - forecasts = pickle.load(f) + with open(path_models + 'diskUP_forecasts.pkl', 'rb') as f: + diskUP_forecasts = pickle.load(f) #Mean Absolute Error (MAE) until this moment - with open(path_models + 'maes.pkl', 'rb') as f: - maes = pickle.load(f) + with open(path_models + 'diskUP_maes.pkl', 'rb') as f: + diskUP_maes = pickle.load(f) #Drifts detected until this moment - with open(path_models + 'drifts_detected.pkl', 'rb') as f: - drifts_detected = pickle.load(f) + with open(path_models + 'diskUP_drifts_detected.pkl', 'rb') as f: + diskUP_drifts_detected = pickle.load(f) #Anomalies detected until this moment - with open(path_models + 'anoms_detected.pkl', 'rb') as f: - anoms_detected = pickle.load(f) + with open(path_models + 'diskUP_anoms_detected.pkl', 'rb') as f: + diskUP_anoms_detected = pickle.load(f) # Plot the results fig, ax = plt.subplots(figsize=(10, 6)) ax.grid(alpha=0.75) - ax.plot(real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') - ax.plot(forecasts, lw=3, color='green', alpha=0.8, label='Prediction') + ax.plot(diskUP_real_obs, lw=3, color='blue', alpha=0.8, label='Ground truth') + ax.plot(diskUP_forecasts, lw=3, color='green', alpha=0.8, label='Prediction') - ax.plot(np.zeros(len(forecasts)), label='Drifts detected',linestyle='--', color='k') - for d in range(len(drifts_detected)): - if drifts_detected[d]==1: + ax.plot(np.zeros(len(diskUP_forecasts)), label='Drifts detected',linestyle='--', color='k') + for d in range(len(diskUP_drifts_detected)): + if diskUP_drifts_detected[d]==1: ax.axvline(d, lw=1, color='k', alpha=0.8,linestyle='--') - ax.plot(np.zeros(len(forecasts)), label='Anomalies detected',linestyle=':', color='k') - for a in range(len(anoms_detected)): - if anoms_detected[a]==1: + ax.plot(np.zeros(len(diskUP_forecasts)), label='Anomalies detected',linestyle=':', color='k') + for a in range(len(diskUP_anoms_detected)): + if diskUP_anoms_detected[a]==1: ax.axvline(a, lw=1, color='k', alpha=0.8,linestyle=':') # ax.plot(np.zeros(len(forecasts)), label='Threshold',linestyle='--', color='red') - ax.axhline(th, lw=1, color='red', alpha=0.8,linestyle='--') + ax.axhline(ths[6], lw=1, color='red', alpha=0.8,linestyle='--') ax.legend(loc='lower right') - res=np.round(np.nanmean(maes),3) - std_res=np.round(np.nanstd(maes),3) - ax.set_title('MAE+-std: '+str(res)+' +- '+str(std_res)) + diskUP_res=np.round(np.nanmean(diskUP_maes),3) + diskUP_std_res=np.round(np.nanstd(diskUP_maes),3) + ax.set_title('DISK USED PERCENT - MAE+-std: '+str(diskUP_res)+' +- '+str(diskUP_std_res)) plt.show() - print('MAE+-std: '+str(res)+' +- '+str(std_res)) + print('DISK USED PERCENT - MAE+-std: '+str(diskUP_res)+' +- '+str(diskUP_std_res)) - plt.savefig(path_models+name+'.png') + plt.savefig(path_models+names[6]+'.png') # def generate_outliers(labels): # diff --git a/src/psl/services/self_learning_service.py b/src/psl/services/self_learning_service.py index 2523a06..9c6b9bd 100644 --- a/src/psl/services/self_learning_service.py +++ b/src/psl/services/self_learning_service.py @@ -1,4 +1,5 @@ import logging +from psl.models.deployment import Deployment # noqa: E501 from psl.repository import deployments_repository @@ -8,7 +9,7 @@ def deployments_deployment_iddelete(deployment_id): # noqa: E501 return None, 204 -def deployments_post(body): # noqa: E501 - logging.info("start monitoring deployment: " + body) - deployments_repository.add(body, body) +def deployments_post(deployment): # noqa: E501 + logging.info("start monitoring deployment: " + deployment.deployment_id) + deployments_repository.add(deployment.deployment_id, deployment.deployment_id) return "do some magic!", 201 diff --git a/test_input_data/psl_data.csv b/test_input_data/psl_data.csv new file mode 100644 index 0000000..b6a5411 --- /dev/null +++ b/test_input_data/psl_data.csv @@ -0,0 +1,1729 @@ +_time;cpu_usage_idle;cpu_usage_system;cpu_usage_user;disk_free;disk_used_percent;mem_free;mem_used_percent +2022-03-03T11:20:00Z;86.04486018208894;3.2523556205060857;10.417961855340419;75957148951.27272;24.960946022060753;336815104;24.960946022060753 +2022-03-03T11:30:00Z;86.09526403666631;3.1191360348688453;10.510266681942825;75951704790.70967;24.966324378989572;334690171.9;24.966324378989572 +2022-03-03T11:40:00Z;85.99982845396688;3.0631379847982383;10.673499975828122;75947976968.25807;24.97000714320635;329988263.9;24.97000714320635 +2022-03-03T11:50:00Z;86.16887369498441;3.0379620836937757;10.527854384644451;75943798817.57378;24.974134792533054;323303793.3;24.974134792533054 +2022-03-03T12:00:00Z;85.31288301725779;3.1739201788378013;11.229233815189524;75939861470.96774;24.978024548383267;322473521.5;24.978024548383267 +2022-03-03T12:10:00Z;85.78674696113919;3.1387317275508657;10.764522379870948;75936095529.29033;24.981744971078328;320252102.2;24.981744971078328 +2022-03-03T12:20:00Z;86.1362570791883;3.120741633442709;10.476172707810573;75932082109.93549;24.98570988018513;317773890.1;24.98570988018513 +2022-03-03T12:30:00Z;85.96898511749984;3.191863725677705;10.556136873253221;75927923678.96774;24.989818048147736;316032495.5;24.989818048147736 +2022-03-03T12:40:00Z;86.29352048955401;3.0497561243680837;10.395862728690094;75924282586.2295;24.993415130954226;314444749.6;24.993415130954226 +2022-03-03T12:50:00Z;86.37724107989649;3.028717472252225;10.324704906434501;75920145573.16129;24.997502139895705;312410904.8;24.997502139895705 +2022-03-03T13:00:00Z;86.01478802957443;3.1995644111379766;10.510593089565942;75916179654.19354;25.001420122753167;310672020.6;25.001420122753167 +2022-03-03T13:10:00Z;85.9173538590818;3.041493642259494;10.750473606889512;75911800303.48387;25.00574654019811;308266017;25.00574654019811 +2022-03-03T13:20:00Z;85.10222226576936;3.1825554166902474;11.389582433219262;75907141565.93549;25.0103489675297;305631033.8;25.0103489675297 +2022-03-03T13:30:00Z;85.33457137502126;3.087086587100853;11.312350977409835;75901838963.6129;25.015587477234217;302412984.7;25.015587477234217 +2022-03-03T13:40:00Z;86.0309117193063;3.0394194156871417;10.656192160701297;75897784420.72131;25.019593012817083;299550587.9;25.019593012817083 +2022-03-03T13:50:00Z;86.36787037200799;3.042271081991661;10.315461110596193;75893954626.06451;25.023376516699777;297927184.5;25.023376516699777 +2022-03-03T14:00:00Z;85.1113594324111;3.118465944029379;11.47458546021703;75890402535.2258;25.02688567337378;295158486.7;25.02688567337378 +2022-03-03T14:10:00Z;83.44411578809877;3.1970906054333965;13.055262633035916;75931228490.32259;24.986553182087516;293768555.4;24.986553182087516 +2022-03-03T14:20:00Z;86.13090081490286;3.1108425792726027;10.50002798606324;75928471684.12903;24.989276666731417;292007801.7;24.989276666731417 +2022-03-03T14:30:00Z;86.37660987634375;3.092765643663567;10.248060480967398;75924313205.5082;24.993384881771128;296340563.9;24.993384881771128 +2022-03-03T14:40:00Z;86.37338718436892;3.0401352678701143;10.31006038212067;75920797897.44263;24.996857700265814;294641664;24.996857700265814 +2022-03-03T14:50:00Z;86.24356020768799;3.0963618616645694;10.386758257651536;75916569765.16129;25.00103472706139;295648619.4;25.00103472706139 +2022-03-03T15:00:00Z;86.06150934290477;2.9772732796110577;10.698049462503677;75913000431.48387;25.0045609181597;310874838.7;25.0045609181597 +2022-03-03T15:10:00Z;86.2420724429166;3.039221001856729;10.470183798729838;75929370161.54839;24.988389049219442;336701638.2;24.988389049219442 +2022-03-03T15:20:00Z;86.23415312711404;3.064372969119142;10.411675637072499;75925445995.35484;24.992265783968996;334627146.3;24.992265783968996 +2022-03-03T15:30:00Z;86.22914671219804;2.9842580702946107;10.524695605092784;75921681894.81967;24.9959843877757;332056098.1;24.9959843877757 +2022-03-03T15:40:00Z;85.73460870455865;3.0616385869725877;10.92730021222423;75917288348.90323;25.00032482884979;330426830.5;25.00032482884979 +2022-03-03T15:50:00Z;85.13707734928778;3.1301192509007314;11.450186340439338;75913680896;25.003888678426378;329053877.7;25.003888678426378 +2022-03-03T16:00:00Z;83.74504149573657;3.4107282722879484;12.350924908839394;75566409265.54839;25.34696283250214;325207601.5;25.34696283250214 +2022-03-03T16:10:00Z;86.01199647418179;3.104409421815316;10.598418688830126;75545263929.80646;25.367852584316527;323778692.1;25.367852584316527 +2022-03-03T16:20:00Z;86.14813897937846;3.082230568940598;10.499245938879016;75541496072.25807;25.371574899725395;322227629.4;25.371574899725395 +2022-03-03T16:30:00Z;86.33882576072872;3.0138691103891087;10.377393505045475;75537301041.54839;25.375719225048407;320185707.4;25.375719225048407 +2022-03-03T16:40:00Z;83.45866021079779;3.719040326381003;12.251594531499308;75288889890.13333;25.621127827887282;318407475.2;25.621127827887282 +2022-03-03T16:50:00Z;85.6584758966946;3.1650709458955566;10.87797871532624;74272456972.59016;26.625275108525816;316227253.7;26.625275108525816 +2022-03-03T17:00:00Z;85.63137207404539;3.161156033430292;10.902485569634312;74268517078.70967;26.62916738086156;313254746.8;26.62916738086156 +2022-03-03T17:10:00Z;85.87911263833514;3.15986925854202;10.65820253687275;74282427689.29033;26.61542490799838;311433546.3;26.61542490799838 +2022-03-03T17:20:00Z;85.84815551252626;3.1119806570196724;10.76656302435204;74278430389.67741;26.619373892202763;309674975;26.619373892202763 +2022-03-03T17:30:00Z;85.70225183717706;3.108662602100188;10.92999296046678;74281033661.93549;26.61680208572781;307137767.2;26.61680208572781 +2022-03-03T17:40:00Z;86.15761176907031;3.0552305753867603;10.517141629853995;74324184617.96721;26.574172695820852;304596331.4;26.574172695820852 +2022-03-03T17:50:00Z;86.38875625072087;3.009455350653421;10.344968259906937;74320600823.74193;26.577713172682202;301412620.6;26.577713172682202 +2022-03-03T18:00:00Z;85.49162843968523;3.0634019405155613;11.103394118776013;74316393703.2258;26.58186944168203;299123414.7;26.58186944168203 +2022-03-03T18:10:00Z;86.19453344578959;2.9555883021115306;10.588119213115032;74312645665.03226;26.58557217729284;296747999;26.58557217729284 +2022-03-03T18:20:00Z;86.17964523332677;3.0449669413906535;10.492021707580594;74305362382.45161;26.592767426749294;296276892.9;26.592767426749294 +2022-03-03T18:30:00Z;86.11897243903888;3.0377263060975883;10.563614541959554;74296294366.96774;26.601725837020908;295740118.7;26.601725837020908 +2022-03-03T18:40:00Z;86.25477795390476;3.0081027307335066;10.46272656316346;74292396296.25807;26.605576791703005;295366920.3;26.605576791703005 +2022-03-03T18:50:00Z;86.20979352496327;2.9624771259311116;10.560172208984941;74288300168.53334;26.60962340948264;292800814.2;26.60962340948264 +2022-03-03T19:00:00Z;86.22423050548099;3.0555197039295083;10.474046348684391;74284594737.54839;26.613284052878694;289760156.9;26.613284052878694 +2022-03-03T19:10:00Z;86.5684635502061;3.0444816146549796;10.112762067148635;74302276442.83871;26.59581606657296;289544588.4;26.59581606657296 +2022-03-03T19:20:00Z;86.07598962305353;3.0396429048757354;10.592554039557047;74299439302.19354;26.598618914665003;287220703;26.598618914665003 +2022-03-03T19:30:00Z;86.17006287901779;3.0446782259706673;10.496514967823781;74292650314.32259;26.60532584395789;285841275.9;26.60532584395789 +2022-03-03T19:40:00Z;86.39659949612799;3.046126769229952;10.288655408864837;74289042200.7742;26.608890346194396;284027738.8;26.608890346194396 +2022-03-03T19:50:00Z;86.3480147251925;2.997519267060076;10.402235902928252;74284805875.40984;26.613075467043107;282372360.3;26.613075467043107 +2022-03-03T20:00:00Z;86.14219477674739;3.0581146019404644;10.542841281788359;74281068376.13115;26.616767791123046;279160932.7;26.616767791123046 +2022-03-03T20:10:00Z;85.34239271998418;3.049337423626569;11.332891024553524;74277024999.2258;26.620762295683075;278905492.6;26.620762295683075 +2022-03-03T20:20:00Z;86.1694652391634;3.132228824073518;10.422080625223801;74271408392.25807;26.62631101465482;277383960.8;26.62631101465482 +2022-03-03T20:30:00Z;86.33918577149436;3.0377826934734227;10.358265227382171;74260851877.16129;26.636739933026597;273667435.4;26.636739933026597 +2022-03-03T20:40:00Z;86.20827277398813;3.002207053457417;10.517160947440232;74256832313.80646;26.6407109118708;270025628.9;26.6407109118708 +2022-03-03T20:50:00Z;86.07458062247322;3.1391891096546694;10.489161833127305;74253067825.54839;26.644429898714;269109578.3;26.644429898714 +2022-03-03T21:00:00Z;86.17916555984074;3.0651739423004782;10.463950170600647;74265326575.21312;26.632319320703974;268697197.1;26.632319320703974 +2022-03-03T21:10:00Z;86.26584677958637;3.037805364160205;10.419412759315568;74300549053.93549;26.59752257650573;268463120.8;26.59752257650573 +2022-03-03T21:20:00Z;86.22603926561726;3.027837906739824;10.47241653545339;74296234842.83871;26.60178464168107;268820083.6;26.60178464168107 +2022-03-03T21:30:00Z;86.37628532517866;2.993001430575892;10.363701671296035;74290282165.67741;26.60766536876189;267756511;26.60766536876189 +2022-03-03T21:40:00Z;86.32178895411852;2.9842659852317515;10.433352303194983;74285881476.12903;26.612012867122736;267545831.2;26.612012867122736 +2022-03-03T21:50:00Z;86.17198977402649;3.049477439546646;10.506469802517193;74282230486.70967;26.615619726989063;268325392.5;26.615619726989063 +2022-03-03T22:00:00Z;86.38455616042651;2.976049646388229;10.351844508261125;74278108985.80646;26.61969141126128;265279025.5;26.61969141126128 +2022-03-03T22:10:00Z;86.44582133328107;2.9599163478198482;10.327329387684957;74274281198.93333;26.6234729316284;267224920.1;26.6234729316284 +2022-03-03T22:20:00Z;85.56163431894767;3.0582958214817553;11.080157822668463;74270332994.06451;26.627373414497455;266259290.8;26.627373414497455 +2022-03-03T22:30:00Z;86.20076503752453;3.017639108527722;10.530142656663156;74266366348.3871;26.63129211528085;277558106.8;26.63129211528085 +2022-03-03T22:40:00Z;86.23210552356643;3.002051243080894;10.48574868313866;74262548215.74193;26.63506409811079;309802809.8;26.63506409811079 +2022-03-03T22:50:00Z;86.14046557467516;3.023283438518013;10.568688424932065;74258409075.6129;26.639153208403272;308353552.5;26.639153208403272 +2022-03-03T23:00:00Z;86.32991074321919;3.0548417979099027;10.339039430306848;74254752008.25807;26.642766072740987;306425591.7;26.642766072740987 +2022-03-03T23:10:00Z;85.99758389107795;3.09072222608517;10.621441592242121;74280349035.35484;26.61747843721874;306163051.4;26.61747843721874 +2022-03-03T23:20:00Z;86.32269566368662;2.973553053024747;10.44896254750997;74270279176.39345;26.627426581673696;304524909.1;26.627426581673696 +2022-03-03T23:30:00Z;86.3375039289168;2.9738609152686117;10.421921533993254;74262612232.25807;26.635000855363064;301758464;26.635000855363064 +2022-03-03T23:40:00Z;86.42641847344893;3.0301578479462967;10.252311002160441;74258906343.2258;26.63866195126999;299918699.4;26.63866195126999 +2022-03-03T23:50:00Z;86.20210095224232;3.018180851574722;10.491425272394789;74254745467.87097;26.642772534074357;297535752.3;26.642772534074357 +2022-03-04T00:00:00Z;86.2062571501817;2.9627752488242263;10.514282563195914;74250965058.06451;26.646507250021983;296564537.8;26.646507250021983 +2022-03-04T00:10:00Z;86.38057804998928;2.936423491923178;10.389360875677253;74247309179.87097;26.650118939571822;295639898.8;26.650118939571822 +2022-03-04T00:20:00Z;86.6729934831482;2.9556464709060966;10.09308191358221;74243471863.60655;26.653909874148365;293507877.8;26.653909874148365 +2022-03-04T00:30:00Z;86.62202566506386;3.1994950288587836;9.910290486441534;74264263629.63934;26.6333694184418;291352643.1;26.6333694184418 +2022-03-04T00:40:00Z;86.1184070554887;3.0051770709175827;10.60260979375165;74291226227.6129;26.606732717714372;289228139.4;26.606732717714372 +2022-03-04T00:50:00Z;86.70693536616211;3.0998097731159544;9.904698237333864;74287552578.06451;26.610361963816466;286735723.4;26.610361963816466 +2022-03-04T01:00:00Z;86.87508722306072;3.0190810096195517;9.812717899312227;74283297230.45161;26.614565876991573;284341941.7;26.614565876991573 +2022-03-04T01:10:00Z;86.78448596950123;3.0815629988036837;9.85441606230656;74279308254.96774;26.61850663768076;281349203.9;26.61850663768076 +2022-03-04T01:20:00Z;86.8648037282151;2.9803150583023483;9.879433361882656;74274974290.58064;26.622788217388173;279641649.5;26.622788217388173 +2022-03-04T01:30:00Z;86.7806392990734;3.030195838035019;9.927480093180733;74268958317.11476;26.628731475710396;277775657.3;26.628731475710396 +2022-03-04T01:40:00Z;86.89421037431319;3.010125844926408;9.781190496269964;74264650851.09677;26.63298687733478;275557607.2;26.63298687733478 +2022-03-04T01:50:00Z;86.76963285480142;3.04223847600166;9.89743795539258;74260916620.3871;26.63667597235294;272568452.1;26.63667597235294 +2022-03-04T02:00:00Z;86.98101211183506;2.987067488949917;9.760432735627077;74256873670.19354;26.64067005535886;270614461.9;26.64067005535886 +2022-03-04T02:10:00Z;86.58898087692859;3.0242197097255525;10.076558549288174;74252963245.41936;26.64453321478174;269694136.7;26.64453321478174 +2022-03-04T02:20:00Z;86.50076271000675;3.0078868476719585;10.212546759585633;74249028508.90323;26.648420392090255;266784432.3;26.648420392090255 +2022-03-04T02:30:00Z;86.46896623023929;3.0405769783436707;10.189863476368087;74244896062.95082;26.652502889118715;266746252.4;26.652502889118715 +2022-03-04T02:40:00Z;85.79890193534251;3.1206837789252804;10.804061762365228;74241161017.80646;26.656192788727484;267019759.5;26.656192788727484 +2022-03-04T02:50:00Z;86.3048319674637;3.076152067877147;10.31883804288586;74236911682.06451;26.660390762697173;267720571.9;26.660390762697173 +2022-03-04T03:00:00Z;87.03743668685648;3.110081173001123;9.551811272728418;74233311694.45161;26.66394723721648;267727508.6;26.66394723721648 +2022-03-04T03:10:00Z;86.70397356527523;3.195009172411027;9.808956321707857;74251034029.41936;26.646439112324735;269533184;26.646439112324735 +2022-03-04T03:20:00Z;86.93706115620749;3.1572915360808347;9.595963960195528;74248201645.41936;26.64923726126525;269242905.2;26.64923726126525 +2022-03-04T03:30:00Z;87.07531590028344;3.051494735945547;9.597530145206981;74241491816.91803;26.655865987988744;268767826.6;26.655865987988744 +2022-03-04T03:40:00Z;87.15314201300883;3.037582438511749;9.523024446970265;74237671054.68852;26.659640568619213;268052215.7;26.659640568619213 +2022-03-04T03:50:00Z;87.22780479744179;2.9478136235938823;9.528559351524253;74233606936.7742;26.663655563491407;267228523.4;26.663655563491407 +2022-03-04T04:00:00Z;86.46863772827905;3.205824975283093;10.064328625907772;74262090124.3871;26.635516652509907;265621570.1;26.635516652509907 +2022-03-04T04:10:00Z;86.83224409218174;3.024020592917004;9.846355104590053;74281534497.03226;26.61630730423088;264113713.5;26.61630730423088 +2022-03-04T04:20:00Z;86.74078160461345;3.0106211121492574;9.977262306990252;74277502843.87097;26.620290226751894;264590369;26.620290226751894 +2022-03-04T04:30:00Z;86.56942045795589;3.0631542403357446;10.089828463318465;74273738818.06451;26.624008756733133;264100880.8;26.624008756733133 +2022-03-04T04:40:00Z;86.91766451197749;2.891052248564751;9.924582870391154;74269552162.13333;26.6281448085037;264025781.7;26.6281448085037 +2022-03-04T04:50:00Z;86.41991199842249;3.086105885444252;10.221887800499767;74265968177.54839;26.631685473423843;264573258.3;26.631685473423843 +2022-03-04T05:00:00Z;85.7563696182113;3.041738172492799;10.907583019919636;74261651720.25807;26.63594975764296;264523776;26.63594975764296 +2022-03-04T05:10:00Z;86.60081356430591;3.0461395233497766;10.072250479618225;74259037150.96774;26.63853272460281;265595012.1;26.63853272460281 +2022-03-04T05:20:00Z;86.47065932918355;3.0154562525074327;10.212975530056488;74254760464.51613;26.642757718693826;265273476.1;26.642757718693826 +2022-03-04T05:30:00Z;86.76467478671334;2.975243163820145;9.961720840471525;74243118575.48387;26.65425889207325;263948657.3;26.65425889207325 +2022-03-04T05:40:00Z;86.72546593006916;3.053819397695769;9.943535490562663;74236070614.70967;26.66122166406078;264966342.2;26.66122166406078 +2022-03-04T05:50:00Z;86.77584102416219;3.029281115461853;9.927442931384395;74232246070.55737;26.664999980901886;264064297.3;26.664999980901886 +2022-03-04T06:00:00Z;86.7320530710925;3.0659859991764478;9.905461574329241;74228279296;26.66891880900745;272113994.3;26.66891880900745 +2022-03-04T06:10:00Z;86.81436590111278;3.0328105222199513;9.865147232327292;74224236940.3871;26.672912304619427;306564393.3;26.672912304619427 +2022-03-04T06:20:00Z;86.65828241610677;3.131098733164508;9.922521860115978;74218538149.16129;26.678542214487123;303763654.2;26.678542214487123 +2022-03-04T06:30:00Z;86.80999860541542;3.089291980110709;9.825402015988734;74214363003.87097;26.682666894746077;302315217.8;26.682666894746077 +2022-03-04T06:40:00Z;86.68789747456727;3.0924014046522625;9.933300335878478;74210803117.41936;26.686183752807313;301666371.1;26.686183752807313 +2022-03-04T06:50:00Z;87.03457134520201;3.028074692946663;9.636058717871737;74206507746.62296;26.690427205405214;299009519.5;26.690427205405214 +2022-03-04T07:00:00Z;87.09279324972367;3.083068276627893;9.539921975397208;74202897894.81967;26.69399342488632;297162619.9;26.69399342488632 +2022-03-04T07:10:00Z;86.30010554854597;3.0946399110466127;10.316864422318481;74220785201.54839;26.67632232224926;294239463.2;26.67632232224926 +2022-03-04T07:20:00Z;86.90416061324996;3.1472346599798717;9.648944376503847;74216548616.25807;26.6805076998822;293289851.9;26.6805076998822 +2022-03-04T07:30:00Z;86.44876151505912;3.155674290632523;9.949513256314017;75761804981.67741;25.153928866745062;290589927.2;25.153928866745062 +2022-03-04T07:40:00Z;86.67270650228849;3.0645783637364787;9.969665690410578;76174215300.12903;24.74650335677494;289754867.4;24.74650335677494 +2022-03-04T07:50:00Z;86.74959692744856;3.1098147632320137;9.858358602227735;76170382369.03226;24.750289959187423;285740659.6;24.750289959187423 +2022-03-04T08:00:00Z;86.79116259877232;3.0138880940490878;9.91440104850812;76166283127.46666;24.754339653170884;282600811.4;24.754339653170884 +2022-03-04T08:10:00Z;86.7864180388041;3.13134276074858;9.797440887526635;76162606773.67741;24.75797157082765;281281436.9;24.75797157082765 +2022-03-04T08:20:00Z;86.69971398833712;3.1572123079024723;9.872200399865907;76158348585.29033;24.762178290440474;279627115.4;24.762178290440474 +2022-03-04T08:30:00Z;87.40022355782021;2.99267399781601;9.296284705030171;76154820872.25807;24.765663363962865;277639035.9;24.765663363962865 +2022-03-04T08:40:00Z;86.91576229978514;3.008481576722283;9.79887790633301;76150794173.93549;24.76964139153437;274248142.5;24.76964139153437 +2022-03-04T08:50:00Z;86.85148914308657;3.0154432806278866;9.8490608731244;76146601059.09677;24.773783824143564;273264102.8;24.773783824143564 +2022-03-04T09:00:00Z;86.79959881224966;3.057777512071218;9.855576541520486;76142941283.09677;24.77739936438702;271358612.6;24.77739936438702 +2022-03-04T09:10:00Z;86.62273090934751;3.02476423677534;10.072492879569483;76138213308.85246;24.78207019154975;269437654.7;24.78207019154975 +2022-03-04T09:20:00Z;86.40453707646068;3.049276095502585;10.284534829243222;76134706605.41936;24.785534509416266;266032821.7;24.785534509416266 +2022-03-04T09:30:00Z;87.12274937689305;3.0981992620585697;9.495672205023583;76127950649.80646;24.792208805712388;269777754.8;24.792208805712388 +2022-03-04T09:40:00Z;86.65794046163597;3.0004174487304613;10.051791556820492;76124284333.41936;24.7958308072892;272102697.3;24.7958308072892 +2022-03-04T09:50:00Z;86.7505087996756;2.9765765368679307;9.98794016100765;76120159132.90323;24.799906146457058;283669890.1;24.799906146457058 +2022-03-04T10:00:00Z;86.99396040120227;3.0358335318657477;9.6825881734525;76116285272.13115;24.80373318382736;285014874.8;24.80373318382736 +2022-03-04T10:10:00Z;86.74841080630412;3.084654255711262;9.903931076824797;76112344987.27869;24.80762584240939;282180508.9;24.80762584240939 +2022-03-04T10:20:00Z;86.76711586259131;3.095491368030733;9.854081659001512;76108529928.25807;24.81139478876574;279866401;24.81139478876574 +2022-03-04T10:30:00Z;86.50881847497949;3.0149940635157075;10.189037660018156;76104593540.12903;24.815283597724086;277334610.6;24.815283597724086 +2022-03-04T10:40:00Z;86.52989102494047;3.1098834372353825;10.082443740262274;76100353453.41936;24.81947243445469;277158945;24.81947243445469 +2022-03-04T10:50:00Z;86.77430389490651;3.1915002037532343;9.732394763365175;76096827193.80646;24.82295607212522;277643858.6;24.82295607212522 +2022-03-04T11:00:00Z;86.642424642388;3.132575112650716;9.922107315756145;76143114240;24.77722849801596;277683418.2;24.77722849801596 +2022-03-04T11:10:00Z;86.69030915525754;3.0188506538982365;9.995219105068772;76184885214.42622;24.735962409860242;278196818.6;24.735962409860242 +2022-03-04T11:20:00Z;86.82281914513753;3.08404332478752;9.806979719522223;76176760303.48387;24.743989114906274;276593036.4;24.743989114906274 +2022-03-04T11:30:00Z;86.30784753777638;2.97726054100049;10.455360547715399;76170525662.96774;24.750148397247465;279376070.2;24.750148397247465 +2022-03-04T11:40:00Z;86.82482103171114;3.0372097616331275;9.849773329261692;76166472142.45161;24.754152922812334;278478055.2;24.754152922812334 +2022-03-04T11:50:00Z;86.78076861997413;3.094766930505411;9.836918102044521;76162497833.29033;24.75807919445098;277630381.4;24.75807919445098 +2022-03-04T12:00:00Z;86.63045416806513;3.013167037667019;10.06807957925415;76158522797.41936;24.76200618401554;276459251.4;24.76200618401554 +2022-03-04T12:10:00Z;86.23489137102158;3.074154098788531;10.39609898660798;76154692442.83871;24.76579024105427;276799686.2;24.76579024105427 +2022-03-04T12:20:00Z;86.47360241530002;3.0359291980872576;10.183402822917012;76150677173.67741;24.769756977608914;276057649.5;24.769756977608914 +2022-03-04T12:30:00Z;86.43310178741976;3.0537450441396476;10.20643964388174;76146819138.06451;24.773568381098944;277546809.8;24.773568381098944 +2022-03-04T12:40:00Z;86.95300141678983;3.019722528597737;9.73844409053215;76142802019.09677;24.77753694510137;276684007.2;24.77753694510137 +2022-03-04T12:50:00Z;87.15232237469918;3.0931361316295876;9.481043270564447;76138782257.54839;24.781508119743556;276957448.3;24.781508119743556 +2022-03-04T13:00:00Z;87.11727940512887;3.0082118903649877;9.599175615863885;76135060798.95082;24.78518459702628;275229511.3;24.78518459702628 +2022-03-04T13:10:00Z;87.31160203395005;2.9850574007505335;9.417195771599438;76130624677.16129;24.789567099358354;277825099.5;24.789567099358354 +2022-03-04T13:20:00Z;86.22876736409987;3.033423812586363;10.435641066403123;76126507074.06451;24.79363493293696;276817061.2;24.79363493293696 +2022-03-04T13:30:00Z;87.20647009142793;3.031186437565606;9.492962631233354;76120250830.45161;24.799815557258043;282276698.8;24.799815557258043 +2022-03-04T13:40:00Z;87.00906312065722;3.0063839552906866;9.704841430688141;76116215543.74193;24.803802069408697;323569267.6;24.803802069408697 +2022-03-04T13:50:00Z;86.76922229791798;3.138815420291028;9.803264437798418;76112187986.58064;24.807780945438125;321161282.1;24.807780945438125 +2022-03-04T14:00:00Z;86.54662380767778;3.062322692349049;10.121120490699306;76108421384.25807;24.811502020793107;318995885.4;24.811502020793107 +2022-03-04T14:10:00Z;86.4982982294087;2.951788991920685;10.258978145177569;76104435947.01639;24.81543928600688;317644397.1;24.81543928600688 +2022-03-04T14:20:00Z;86.68126513519007;2.9878113339638057;10.045141863618053;76101231715.09677;24.818604788336735;314875904;24.818604788336735 +2022-03-04T14:30:00Z;86.61123125389504;3.0185772918955354;10.072103212784649;76152297075.6129;24.768156655447605;312931162.8;24.768156655447605 +2022-03-04T14:40:00Z;86.66755852004698;3.0569161700397323;9.968903156638575;76148260203.35484;24.77214473398212;310916657.5;24.77214473398212 +2022-03-04T14:50:00Z;86.75330016085466;3.0372090639789127;9.90060547968332;76144216790.70967;24.776139273849974;307809775.5;24.776139273849974 +2022-03-04T15:00:00Z;86.7078146709941;3.0845991116987506;9.903508109367202;76140528805.16129;24.779782682672668;306151556.1;24.779782682672668 +2022-03-04T15:10:00Z;86.70821131178432;2.973639417838653;10.034308932031015;76158406723.14754;24.762120855296242;303844583.2;24.762120855296242 +2022-03-04T15:20:00Z;86.78107533770732;3.0105240743204784;9.919601089064765;76155385083.80328;24.765105972049383;301628432.8;24.765105972049383 +2022-03-04T15:30:00Z;86.0112827062805;3.0421564774069974;10.637339228051909;76148956126.96774;24.771457222006294;298344514.1;24.771457222006294 +2022-03-04T15:40:00Z;86.60139426004622;3.053769855582516;10.074660871626909;76144745372.90323;24.775617080635772;296755926.7;24.775617080635772 +2022-03-04T15:50:00Z;86.66226284459225;3.0291410076507566;10.007934820746689;76141122130.58064;24.779196528784798;295589491.6;24.779196528784798 +2022-03-04T16:00:00Z;86.98939168100239;3.02319397123893;9.699041231668714;76136964822.70967;24.783303587225515;294531270.2;24.783303587225515 +2022-03-04T16:10:00Z;87.08647859954372;3.078327993172402;9.542405804390862;76133136648.25807;24.787085490486465;292132665.8;24.787085490486465 +2022-03-04T16:20:00Z;86.7059864774067;3.045066709673736;9.977253989875665;76129195998.42622;24.79097850963636;290311923.4;24.79097850963636 +2022-03-04T16:30:00Z;86.46465540995581;3.053453114425753;10.204175738698247;76125191597.41936;24.794934509400083;288019506.4;24.794934509400083 +2022-03-04T16:40:00Z;86.50637650162456;3.10820267556129;10.099679911885548;76121383836.90323;24.798696245469042;285554093.4;24.798696245469042 +2022-03-04T16:50:00Z;86.60021455802536;3.048347944136276;10.061532460523257;76117228709.16129;24.80280115013195;283541570.1;24.80280115013195 +2022-03-04T17:00:00Z;86.9059420734778;3.0052848114450956;9.810776903021909;76113587827.6129;24.80639802430126;280302559;24.80639802430126 +2022-03-04T17:10:00Z;86.97361376790508;3.145955260953574;9.585401053419911;76110133446.19354;24.809810652570835;278493448.3;24.809810652570835 +2022-03-04T17:20:00Z;86.92840160549842;3.09151746675168;9.698775878228775;76106697562.83871;24.813205006362214;276655797.7;24.813205006362214 +2022-03-04T17:30:00Z;87.27312053154967;2.9908369608447583;9.45721606538646;76099872290.13333;24.819947781914276;270524013.1;24.819947781914276 +2022-03-04T17:40:00Z;86.54778911475739;3.0632504283425335;10.106040739256448;76089651200;24.83004532960819;266641209.8;24.83004532960819 +2022-03-04T17:50:00Z;86.75288579951497;3.0672381984849313;9.871612002063346;76092545948.90323;24.827185569569785;266824340.6;24.827185569569785 +2022-03-04T18:00:00Z;87.18940539907884;3.1438191335374275;9.371798268593734;76135367052.3871;24.784882045278966;264665550.5;24.784882045278966 +2022-03-04T18:10:00Z;87.16084069866076;3.109468450865866;9.443070998916653;76131362155.35484;24.78883853507261;262681170.6;24.78883853507261 +2022-03-04T18:20:00Z;87.12640670377814;3.032895471453612;9.559879086411481;76127411299.09677;24.79274163728355;261696545;24.79274163728355 +2022-03-04T18:30:00Z;86.73411167899054;3.0567348600680835;9.928707116749147;76123570506.32259;24.796536006349267;263623647;24.796536006349267 +2022-03-04T18:40:00Z;86.91130724436995;2.9286539560234726;9.87916034638987;76119464976.78688;24.800591912300064;263403656.5;24.800591912300064 +2022-03-04T18:50:00Z;86.82972863126015;2.968465035295827;9.918845835817004;76115794382.45161;24.804218140117438;262343118.5;24.804218140117438 +2022-03-04T19:00:00Z;86.74165488995975;3.0538643720603638;9.931056141206827;76111543461.16129;24.80841768047097;261687229.9;24.80841768047097 +2022-03-04T19:10:00Z;86.70426506692725;3.038860442678118;9.970699316625451;76130114526.96774;24.79007108336038;261958358.7;24.79007108336038 +2022-03-04T19:20:00Z;86.74066739450795;3.014978450541377;9.986194913032021;76126537331.6129;24.79360504111193;263225079.7;24.79360504111193 +2022-03-04T19:30:00Z;86.54505261650829;3.085929954137272;10.084975088467129;76120484368.51613;24.799584841970912;264311444.6;24.799584841970912 +2022-03-04T19:40:00Z;86.46264703334695;3.0543452385906837;10.184332084422309;76116186632.39345;24.803830631305377;264649677.6;24.803830631305377 +2022-03-04T19:50:00Z;85.97786012916752;3.040581245561238;10.66858761257938;76107996655.48387;24.811921615865487;264769602.1;24.811921615865487 +2022-03-04T20:00:00Z;86.7397920786817;3.0555928680013036;9.917351405647677;76100026037.67741;24.819795892718616;263473019.9;24.819795892718616 +2022-03-04T20:10:00Z;86.52953119740596;3.1317527430658707;10.048718638241308;76096131468.3871;24.823643388303065;263956017.5;24.823643388303065 +2022-03-04T20:20:00Z;86.81941441858159;3.087450267591227;9.81232074220788;76092241589.67741;24.827486250001968;263375112.3;24.827486250001968 +2022-03-04T20:30:00Z;86.888435639587;2.935027271280792;9.87614439434981;76088202961.83606;24.831476062900016;263588698.8;24.831476062900016 +2022-03-04T20:40:00Z;86.95570384930029;3.013204821090777;9.75700848774588;76084438804.98361;24.835194722343296;264862468.2;24.835194722343296 +2022-03-04T20:50:00Z;86.94248275803612;3.003449021048088;9.78952413085002;76080237865.29033;24.839344885227966;264981655.1;24.839344885227966 +2022-03-04T21:00:00Z;86.86938756595667;3.0084368822016154;9.851250373301735;76076665426.58064;24.842874143827977;265754293.7;24.842874143827977 +2022-03-04T21:10:00Z;86.73038615337975;3.1078758178449033;9.88789259432314;76071935471.48387;24.84754692790057;307532370.6;24.84754692790057 +2022-03-04T21:20:00Z;86.41181649605063;3.160113443154931;10.151291990098914;76085419041.03226;24.834226334419565;305079329;24.834226334419565 +2022-03-04T21:30:00Z;86.6109834046621;3.075147206158984;10.01331916260034;76114421760;24.80557417166495;309991093.7;24.80557417166495 +2022-03-04T21:40:00Z;86.68796445836378;3.0922513191330023;9.916811813470753;76105131662.68852;24.81475197945845;308575450.2;24.81475197945845 +2022-03-04T21:50:00Z;86.80337814575974;3.0440428054444544;9.881625551044259;76101021696;24.818812268930163;306239620.1;24.818812268930163 +2022-03-04T22:00:00Z;86.30979736506102;3.053883998483449;10.372718034220629;76097161149.93549;24.82262615252794;301460843.4;24.82262615252794 +2022-03-04T22:10:00Z;86.84250014597822;3.0555111772902626;9.817961017416316;76093246893.41936;24.826493097378467;297982018.1;24.826493097378467 +2022-03-04T22:20:00Z;86.51732604244253;3.0189126900707506;10.163945720348469;76089211738.83871;24.830479478997137;299068911.5;24.830479478997137 +2022-03-04T22:30:00Z;86.56386895821935;3.0439590152924954;10.084576274742005;76085467003.87097;24.83417895130826;295930318.5;24.83417895130826 +2022-03-04T22:40:00Z;86.54463157987938;3.1918078969895207;9.96916589084647;76081254994.58064;24.838340049991615;292767677.9;24.838340049991615 +2022-03-04T22:50:00Z;86.7180358501985;3.01765472148344;9.985499273010262;76077699686.4;24.841852385119502;290788200.9;24.841852385119502 +2022-03-04T23:00:00Z;86.6373253365463;3.110579057336295;9.927783484543356;76073355990.70967;24.84614357850775;289968590.5;24.84614357850775 +2022-03-04T23:10:00Z;86.45785431120706;3.0540322913130864;10.2009870233564;76087165588.64516;24.83250089734868;288107817.3;24.83250089734868 +2022-03-04T23:20:00Z;86.88728868522492;2.9088715923499278;9.945876696657837;76078091032.7742;24.841465768953636;286719207.2;24.841465768953636 +2022-03-04T23:30:00Z;86.50955849343536;3.0581690175750884;10.140588461341697;76072395742.96774;24.847092219723677;283166323.6;24.847092219723677 +2022-03-04T23:40:00Z;86.72473044170424;3.0468581863119244;9.956882010532773;76068297761.03226;24.85114066930218;282070049;24.85114066930218 +2022-03-04T23:50:00Z;86.71723005775938;3.0690232125395176;9.938176097930382;76064447653.16129;24.854944240872992;280581417.3;24.854944240872992 +2022-03-05T00:00:00Z;86.72593578898987;3.040019971829609;9.938387641605292;76060499699.40984;24.858844475659943;278056422.8;24.858844475659943 +2022-03-05T00:10:00Z;85.97134573570034;3.0177935887889187;10.751724984604033;76056674832.51613;24.862623111341488;278312167.2;24.862623111341488 +2022-03-05T00:20:00Z;86.89349380526822;2.9699146836760324;9.861593914696893;76052944763.87097;24.866308094602054;279354004.6;24.866308094602054 +2022-03-05T00:30:00Z;86.87316221954593;3.0798703967431376;9.758923136305901;76048771930.83871;24.870430490551243;278628616.3;24.870430490551243 +2022-03-05T00:40:00Z;86.75317138259896;3.136811395631067;9.799877807970029;76045158862.45161;24.873999887737266;276328778.3;24.873999887737266 +2022-03-05T00:50:00Z;86.49405129801985;3.112451641854952;10.127355608290616;76065959737.80646;24.85345043281313;273001703.2;24.85345043281313 +2022-03-05T01:00:00Z;86.8320581291233;3.016512983516745;9.87694282627315;76093011241.29033;24.826725901177365;272722155;24.826725901177365 +2022-03-05T01:10:00Z;86.72251061587974;3.0488810635615;9.948813974754291;76088312149.33333;24.831368195153324;269263394.1;24.831368195153324 +2022-03-05T01:20:00Z;86.77884339835877;3.0682571363931213;9.88408013467673;76084712348.90323;24.834924484752328;266534449.5;24.834924484752328 +2022-03-05T01:30:00Z;86.74663166440023;3.0751666971997684;9.863332362137546;76078148971.35484;24.84140853067731;264489092.1;24.84140853067731 +2022-03-05T01:40:00Z;86.85712601130489;3.0739146012720946;9.803659056670273;76074239735.74193;24.845270515312322;262864631.7;24.845270515312322 +2022-03-05T01:50:00Z;86.91326561778385;3.1051670418978454;9.706761217854098;76070235367.2258;24.84922648297802;263671147.4;24.84922648297802 +2022-03-05T02:00:00Z;86.83728493265673;3.08436599463971;9.810102957459971;76066291910.19354;24.85312227539767;260900467.6;24.85312227539767 +2022-03-05T02:10:00Z;86.70421211669287;3.128951603446621;9.904396014443993;76061508574.96774;24.857847794393056;258661034.7;24.857847794393056 +2022-03-05T02:20:00Z;86.74348114776325;3.14960096988197;9.842044928441085;76049918657.04918;24.869297624834278;256353180.9;24.869297624834278 +2022-03-05T02:30:00Z;86.19047119430256;3.0735425760439283;10.439869818786027;76046281827.09677;24.872890496379288;255850429.9;24.872890496379288 +2022-03-05T02:40:00Z;86.96166522885237;2.9636047410701614;9.800442296655737;76042015644.90323;24.87710511317733;254416763.9;24.87710511317733 +2022-03-05T02:50:00Z;86.86255121666412;3.0654269954971434;9.791285780624754;76038477824;24.880600172396733;252586116.1;24.880600172396733 +2022-03-05T03:00:00Z;86.70600504456425;3.0662537796595175;9.918821744175448;76034155685.16129;24.884870069491274;248755563.4;24.884870069491274 +2022-03-05T03:10:00Z;86.59515700090603;3.028453708039256;10.02581204389715;76052616423.2258;24.866632466589884;247105604.3;24.866632466589884 +2022-03-05T03:20:00Z;86.8165219564152;3.042502800349269;9.866916920207068;76049139476.98361;24.870067386941017;245207172.1;24.870067386941017 +2022-03-05T03:30:00Z;86.73222179144734;3.052874765260744;9.923925312435218;76042929806.68852;24.87620200087653;244964451.1;24.87620200087653 +2022-03-05T03:40:00Z;86.88946585658032;3.0727480449133218;9.769352619904303;76038829485.41936;24.880252761513184;244967688.3;24.880252761513184 +2022-03-05T03:50:00Z;86.79724952737529;3.089051748697238;9.840427774523857;76034933462.70967;24.88410169294949;242360187.9;24.88410169294949 +2022-03-05T04:00:00Z;86.85189880163414;3.1026286554448035;9.76283533034159;76031045962.32259;24.887942205072626;240386444.4;24.887942205072626 +2022-03-05T04:10:00Z;86.80595096567271;3.044527504229282;9.856056883089542;76026996273.54839;24.89194294520988;238238026.3;24.89194294520988 +2022-03-05T04:20:00Z;86.8392336658582;3.042265123915129;9.849078149452104;76055561381.16129;24.863723104396406;236908006.8;24.863723104396406 +2022-03-05T04:30:00Z;86.85174262373526;2.9802162135542254;9.893131883782855;76074664540.32787;24.84485084534453;246442578.6;24.84485084534453 +2022-03-05T04:40:00Z;86.76246483640637;3.015155870049376;9.952301395429531;76071120565.67741;24.848351983930733;294615832.8;24.848351983930733 +2022-03-05T04:50:00Z;86.37604218244772;3.044150196563362;10.273039833306878;76066823333.16129;24.852597275745737;295102464;24.852597275745737 +2022-03-05T05:00:00Z;86.80980889608966;3.0586739293082585;9.836383638652084;76063262587.87097;24.8561149822649;292664287;24.8561149822649 +2022-03-05T05:10:00Z;86.78369150080047;3.087752673772038;9.821690383695264;76077183306.32259;24.84236252370471;291208423.2;24.84236252370471 +2022-03-05T05:20:00Z;86.53763448308261;3.0566579541420076;10.1141246299894;76074064136.25807;24.845443992323123;294139131.8;24.845443992323123 +2022-03-05T05:30:00Z;86.56748514402209;3.0408681059108575;10.115827012230433;76067571910.19354;24.851857746773085;295683303.2;24.851857746773085 +2022-03-05T05:40:00Z;86.6963334005126;3.015171615827007;10.02483720470454;76063567462.4;24.855813792757957;294423254.7;24.855813792757957 +2022-03-05T05:50:00Z;86.73132780181567;3.0675635971847344;9.92398808233335;76059708382.96774;24.859626227450693;293893285.2;24.859626227450693 +2022-03-05T06:00:00Z;86.94882019137314;3.006447351924431;9.785300873705928;76055655523.09677;24.863630100355632;292522084.7;24.863630100355632 +2022-03-05T06:10:00Z;86.53924219718498;3.1490016689349;10.016111906340862;76051918319.48387;24.8673221323435;290558414.5;24.8673221323435 +2022-03-05T06:20:00Z;86.62931681338205;3.1330108591442247;9.962644153559346;76047726195.6129;24.871463585962793;290115451.9;24.871463585962793 +2022-03-05T06:30:00Z;86.69146620395682;3.0899914880008383;9.949520396009392;76044120856.7742;24.875025347027577;289096538.8;24.875025347027577 +2022-03-05T06:40:00Z;86.5498672483048;2.993956015833792;10.173285071001454;76039804861.93549;24.879289174384734;285046255.5;24.879289174384734 +2022-03-05T06:50:00Z;86.70859419733185;2.973741696130453;10.045855983515002;76036253192.39345;24.882797914854294;284021206;24.882797914854294 +2022-03-05T07:00:00Z;85.95353200606459;3.1425986310004803;10.631486631880819;76032011825.54839;24.886988016247255;283055355.8;24.886988016247255 +2022-03-05T07:10:00Z;86.84029873568288;3.0405443904346625;9.829528601291772;76050466485.67741;24.868756417817263;281931908.1;24.868756417817263 +2022-03-05T07:20:00Z;86.67577800384835;3.0774952813482654;9.949020311804025;76047101027.09677;24.87208119805954;279594281.3;24.87208119805954 +2022-03-05T07:30:00Z;86.6550791487404;3.052888028241218;9.97748932526715;76040806862.45161;24.87829928506091;278592677.2;24.87829928506091 +2022-03-05T07:40:00Z;86.85387380214927;3.038262572779916;9.829213825652378;76034218380.3871;24.884808132063434;276528689.5;24.884808132063434 +2022-03-05T07:50:00Z;86.64643946374161;3.0781370414700384;10.006540644694129;76064504110.16394;24.854888466266825;274961969.5;24.854888466266825 +2022-03-05T08:00:00Z;86.6258351165169;3.068491654224262;10.027945278598663;76076200068.12903;24.84333387748638;270188879.7;24.84333387748638 +2022-03-05T08:10:00Z;86.63444803912579;3.050581630190458;10.06353407402679;76072065882.83871;24.847418092829347;266497585.5;24.847418092829347 +2022-03-05T08:20:00Z;86.44042062365165;2.997587642372198;10.270082853161473;76068450568.25807;24.850989709059153;264074008.8;24.850989709059153 +2022-03-05T08:30:00Z;86.4446760195348;3.078835152667079;10.19466260353789;76064114291.6129;24.85527357307633;262203061.7;24.85527357307633 +2022-03-05T08:40:00Z;86.73513748863247;3.0191311013537883;9.937463093106299;76060595034.83871;24.85875029255155;261823455;24.85875029255155 +2022-03-05T08:50:00Z;86.52344118721838;3.077021139203878;10.122211922661412;76056307645.93549;24.86298585973351;263448642.1;24.86298585973351 +2022-03-05T09:00:00Z;86.7240948074418;3.0366200381550468;9.96585318698506;76052648618.66667;24.866600660295706;263302969.8;24.866600660295706 +2022-03-05T09:10:00Z;85.94252456906499;3.099964131012582;10.66078178235268;76048100913.54839;24.871093397247492;264189314.1;24.871093397247492 +2022-03-05T09:20:00Z;86.37053329256528;3.071310297842545;10.273057987071162;76044276306.58064;24.874871776144808;262916162.1;24.874871776144808 +2022-03-05T09:30:00Z;86.61771540439842;2.987458175045624;10.082775895477061;76037845124.12903;24.881225224816735;262696035.1;24.881225224816735 +2022-03-05T09:40:00Z;86.65376469448252;3.032726224205845;10.03027330542733;76033809969.54839;24.885211606435412;264376716.4;24.885211606435412 +2022-03-05T09:50:00Z;86.6075075928006;3.0074411608108225;10.088442228586548;76029985098.32259;24.888990246396695;263710389.7;24.888990246396695 +2022-03-05T10:00:00Z;86.5199943114806;3.0670575531919124;10.116271785691795;76025887357.90164;24.893038457379852;263598080;24.893038457379852 +2022-03-05T10:10:00Z;86.5327269743238;3.038941168131839;10.147531684264553;76022205658.2295;24.896675656303756;263006711.6;24.896675656303756 +2022-03-05T10:20:00Z;86.47625992783848;3.175898855802075;10.07145248759849;76017938365.93549;24.900891369784475;262662804.6;24.900891369784475 +2022-03-05T10:30:00Z;86.31245901211769;3.266927150179408;10.138530227671582;76014458880;24.904328799131594;263913802.3;24.904328799131594 +2022-03-05T10:40:00Z;86.69589775531757;3.027691983650574;9.993247857498083;76010139846.19354;24.90859562872446;262859346.6;24.90859562872446 +2022-03-05T10:50:00Z;86.73461782317024;3.0727724967252295;9.906391393079453;76006510459.87097;24.912181146610884;260978820.1;24.912181146610884 +2022-03-05T11:00:00Z;86.7807600564964;3.063895187327469;9.863589465465555;76002331945.29033;24.916309155435517;261513216;24.916309155435517 +2022-03-05T11:10:00Z;86.5523733594766;3.0463928089857206;10.120375329644189;76021982795.54099;24.89689582524828;261668335.5;24.89689582524828 +2022-03-05T11:20:00Z;86.50259716112991;3.1025794827993547;10.12824652497409;76067212387.09677;24.852212924309857;263003287.1;24.852212924309857 +2022-03-05T11:30:00Z;86.14088781375267;3.0937351332417937;10.48542991610834;76068021479.2258;24.851413611687114;262488658.6;24.851413611687114 +2022-03-05T11:40:00Z;86.49239174644806;3.1473229660960733;10.0731556167121;76064094208;24.855293413938362;260684040.3;24.855293413938362 +2022-03-05T11:50:00Z;86.70950944516;2.9961905759131877;10.019156959109967;76060018159.48387;24.859320195207044;258562576.5;24.859320195207044 +2022-03-05T12:00:00Z;86.26928224342129;3.1376713804096594;10.299347143417359;76056327861.67741;24.862965888339506;255920788.6;24.862965888339506 +2022-03-05T12:10:00Z;86.70978979231454;3.0030563798895185;9.992672347417304;76051399316.64516;24.867834861988648;293719667.6;24.867834861988648 +2022-03-05T12:20:00Z;86.6944994586484;3.083217224417812;9.935891184809671;76033156300.8;24.885857374281787;297797598.4;24.885857374281787 +2022-03-05T12:30:00Z;86.57981632204749;3.093475910423843;10.025519219461954;76027452779.35484;24.891491957194603;295177635.7;24.891491957194603 +2022-03-05T12:40:00Z;86.75178850717533;3.0610996373330597;9.897977934891092;76023885031.2258;24.89501658190907;292833346.1;24.89501658190907 +2022-03-05T12:50:00Z;86.80272264000185;3.0355953715622195;9.891058621766554;76019647653.16129;24.899202742733937;291708531.6;24.899202742733937 +2022-03-05T13:00:00Z;86.57929288116489;3.02043247095791;10.137547786128946;76015936611.09677;24.902868929388358;289964824.8;24.902868929388358 +2022-03-05T13:10:00Z;86.41287590154434;2.9465167545554998;10.356770713289066;76011423876.12903;24.907327118874246;287923959.7;24.907327118874246 +2022-03-05T13:20:00Z;86.57383929802015;3.0419301606340636;10.076606392609873;76007504268.3871;24.911199350270245;286365828.1;24.911199350270245 +2022-03-05T13:30:00Z;86.5023337232912;3.047856807336825;10.167152862400625;76001097828.72131;24.917528355222707;285526989.6;24.917528355222707 +2022-03-05T13:40:00Z;85.59348459164582;3.096677102535941;11.023407620764754;75996991818.32259;24.921584736224347;284370415.5;24.921584736224347 +2022-03-05T13:50:00Z;86.45216255325742;3.1190672749304116;10.142991285099773;75993212994.06451;24.92531788578813;282997660.9;24.92531788578813 +2022-03-05T14:00:00Z;86.63025596009582;3.146541401811546;9.940365206601697;75988997813.67741;24.92948211723917;281772296.3;24.92948211723917 +2022-03-05T14:10:00Z;86.85914849102933;3.0797429434968286;9.793830897074765;75985421477.16129;24.9330152265328;278620556.4;24.9330152265328 +2022-03-05T14:20:00Z;86.75124133355538;3.068891485133923;9.899873569137293;75981085662.96774;24.937298633688012;277111114.3;24.937298633688012 +2022-03-05T14:30:00Z;86.57888761105784;3.1182893157611096;10.00465559044239;75977563499.35484;24.94077822486695;274443759.5;24.94077822486695 +2022-03-05T14:40:00Z;86.1952873081455;3.117994534820855;10.369091427368037;75973844727.74193;24.944452047642617;271939147.5;24.944452047642617 +2022-03-05T14:50:00Z;86.4101491116449;3.1781290460196048;10.117064691458738;76027271168;24.891671373410805;271357489.5;24.891671373410805 +2022-03-05T15:00:00Z;86.62387207690422;3.0930367671105192;9.976761891192666;76023160303.48387;24.895732549858067;270224483.1;24.895732549858067 +2022-03-05T15:10:00Z;86.77262469635224;3.0226114685324044;9.938653366278366;76041370326.70967;24.877742631402118;268309471;24.877742631402118 +2022-03-05T15:20:00Z;86.62530454275664;3.1252423484257545;9.962653127341891;76038172936.25807;24.88090137495686;266663341.4;24.88090137495686 +2022-03-05T15:30:00Z;86.78965227820966;3.0355384781692334;9.907754133973105;76031698679.74193;24.887297377056573;264981933.4;24.887297377056573 +2022-03-05T15:40:00Z;85.97874333825396;3.0615369474155636;10.66837752894242;76027842493.93549;24.89110695309878;264378133;24.89110695309878 +2022-03-05T15:50:00Z;86.81070445632207;3.1068386066289473;9.809739358399415;76023676795.87097;24.895222300320675;264111893;24.895222300320675 +2022-03-05T16:00:00Z;86.65008493931221;3.065752475862931;9.976619959134807;76020063661.41936;24.898791762772692;261452965.2;24.898791762772692 +2022-03-05T16:10:00Z;86.42619016793604;3.095448279308823;10.201889085299198;76015753876.64516;24.903049455126467;258702170.8;24.903049455126467 +2022-03-05T16:20:00Z;86.71508916231802;3.004367002390839;9.989397293062208;76012290316.59016;24.90647115108939;257549279;24.90647115108939 +2022-03-05T16:30:00Z;86.45153585254891;3.037099200465674;10.22300732015244;76007965410.62296;24.910743781866145;256155846.2;24.910743781866145 +2022-03-05T16:40:00Z;86.48524849722693;3.0500082615259116;10.17970476665123;76003510932.64516;24.91514441851502;254440547.1;24.91514441851502 +2022-03-05T16:50:00Z;86.4819633950347;3.100714749865822;10.141430471511468;75991773514.32259;24.926739966521104;251685770.5;24.926739966521104 +2022-03-05T17:00:00Z;86.53499805424322;3.1152568856211347;10.050121182174093;75987961657.80646;24.930505749081664;251970460.9;24.930505749081664 +2022-03-05T17:10:00Z;86.60990814162054;3.0703006906606882;10.021362707229732;75984871357.93549;24.9335586964609;251643507.6;24.9335586964609 +2022-03-05T17:20:00Z;86.30743180830706;3.126156602941227;10.22319317167317;75980935564.3871;24.937446918025305;252692281.8;24.937446918025305 +2022-03-05T17:30:00Z;86.55002661604752;3.126897757737554;10.049994852625735;75974697027.14754;24.943610049990184;252035600.5;24.943610049990184 +2022-03-05T17:40:00Z;86.41828591267995;3.0996974119003737;10.16540615111295;75970484290.06451;24.947771867669402;251946611.6;24.947771867669402 +2022-03-05T17:50:00Z;86.08636617580412;3.071841247912784;10.53710267915664;75966813150.96774;24.951398633663732;252360043.4;24.951398633663732 +2022-03-05T18:00:00Z;86.7617113621962;3.0481486935663558;9.888501038146687;75962517636.12903;24.955642228562905;250461388.8;24.955642228562905 +2022-03-05T18:10:00Z;86.54423211164841;3.26064336442973;9.893740912033074;75967964259.09677;24.95026143899251;251616751.5;24.95026143899251 +2022-03-05T18:20:00Z;86.90019255360986;3.1047101082464694;9.712151844086101;76010275740.90323;24.90846137657577;252085413.2;24.90846137657577 +2022-03-05T18:30:00Z;86.46123541338918;3.1227611553046066;10.13540519377846;76006499691.35484;24.91219178496783;251471211.4;24.91219178496783 +2022-03-05T18:40:00Z;86.7730654201448;3.0184651638293998;9.926450060317;76002477806.93333;24.91616505682394;251575989.7;24.91616505682394 +2022-03-05T18:50:00Z;86.66313194983046;3.0395194190349613;9.998797926021771;75998541361.54839;24.920053922346145;251733817.8;24.920053922346145 +2022-03-05T19:00:00Z;86.7469502884789;3.0538042695081784;9.912110521053476;75994661260.3871;24.923887124678014;251219027.9;24.923887124678014 +2022-03-05T19:10:00Z;86.28916944748785;3.013251703577327;10.408984243492766;76012629487.48387;24.906136079758365;251346205.4;24.906136079758365 +2022-03-05T19:20:00Z;86.61648909908263;3.004013603104463;10.102166652369426;76009647863.74193;24.909081664578256;251905387.4;24.909081664578256 +2022-03-05T19:30:00Z;86.57783291609856;3.0542846493061577;10.07884280781257;76003011484.90323;24.915637829426082;251019396.1;24.915637829426082 +2022-03-05T19:40:00Z;86.45332674388273;3.1162504634153527;10.108611346067365;75999343129.18033;24.919261845689228;284588494.5;24.919261845689228 +2022-03-05T19:50:00Z;85.97675402838703;3.143080403445569;10.586884620168382;75995018933.67741;24.92353377458906;290643373.4;24.92353377458906 +2022-03-05T20:00:00Z;86.57923629151693;3.097700634974043;10.033995800385064;75991429780.64516;24.927079545485427;287911407.5;24.927079545485427 +2022-03-05T20:10:00Z;86.86881034218219;3.10422901772363;9.715270266043792;75987160030.96774;24.931297686647124;286018845.4;24.931297686647124 +2022-03-05T20:20:00Z;86.84081740464434;3.1366190270243384;9.733903194952331;75983415362.06451;24.934997093692253;284345112.8;24.934997093692253 +2022-03-05T20:30:00Z;86.72327125762675;3.137080856743553;9.838536581123662;75979314076.90323;24.939048806570447;282608144.5;24.939048806570447 +2022-03-05T20:40:00Z;86.64059714748826;3.049621086506089;10.008102424942356;75975422354.88524;24.94289348929757;278385168.5;24.94289348929757 +2022-03-05T20:50:00Z;86.7498753756652;3.0768600070718612;9.879538414478098;75971436544;24.946831123638688;277495543.7;24.946831123638688 +2022-03-05T21:00:00Z;86.45651197375078;3.189420170862663;10.049917776722639;75967395311.48387;24.95082350972877;275574717.9;24.95082350972877 +2022-03-05T21:10:00Z;86.51461717206318;2.9563484357543044;10.240295222841667;75963142870.70967;24.955024551200147;274246404.2;24.955024551200147 +2022-03-05T21:20:00Z;86.55584102226814;3.0649533388679346;10.089190443327634;75955408631.74193;24.96266530632843;273354884.1;24.96266530632843 +2022-03-05T21:30:00Z;86.63578760811028;3.0521233070541416;10.024664311072955;75944451699.6129;24.97348980188698;270394929.5;24.97348980188698 +2022-03-05T21:40:00Z;86.46147624204501;3.1644046376346275;10.081058629814777;75957099024.51613;24.960995345352035;268489034.3;24.960995345352035 +2022-03-05T21:50:00Z;86.49350898292107;3.0594763140565333;10.16326583061164;75992188894.42622;24.92632960712177;266249513.3;24.92632960712177 +2022-03-05T22:00:00Z;86.49569580303582;3.1282754727234896;10.100192961923804;75987886542.45161;24.93057995651629;264404992;24.93057995651629 +2022-03-05T22:10:00Z;86.52266548634276;3.0265800953193054;10.161366128159136;75984221745.54839;24.934200456975258;261774369;24.934200456975258 +2022-03-05T22:20:00Z;86.21609251520312;3.1500970415804344;10.35711565291692;75980101103.48387;24.93827129278955;261505024;24.93827129278955 +2022-03-05T22:30:00Z;86.49027363335811;3.0738378862425244;10.169314382461007;75976272862.96774;24.942053261316506;260073538.1;24.942053261316506 +2022-03-05T22:40:00Z;86.48455965948072;3.069609975560845;10.153351798465472;75972302385.54839;24.945975747527516;253950810.8;24.945975747527516 +2022-03-05T22:50:00Z;86.7435256825627;2.9980832786551987;9.963609791023528;75968350107.27869;24.949880254562213;253058147.1;24.949880254562213 +2022-03-05T23:00:00Z;86.46492479540102;3.117165391746159;10.132274983692175;75964503865.80646;24.953680006467486;252528970.3;24.953680006467486 +2022-03-05T23:10:00Z;86.37119117593514;3.1483850930690434;10.163952484266012;76009598645.67741;24.909130287743423;253452618.3;24.909130287743423 +2022-03-05T23:20:00Z;86.70086279800114;3.143199517440225;9.818204138356034;76007580176.51613;24.911124359643676;253865257.3;24.911124359643676 +2022-03-05T23:30:00Z;87.1311448402347;3.1425467838577985;9.435437545487586;76000829043.6129;24.91779389152227;253186786.6;24.91779389152227 +2022-03-05T23:40:00Z;87.05778212840507;3.0949202453035562;9.533451091159987;75997242082.62296;24.92133749687158;252454317.4;24.92133749687158 +2022-03-05T23:50:00Z;86.4302184021682;3.152593215402521;10.139598801632431;75992931955.6129;24.9255955273246;252776580.1;24.9255955273246 +2022-03-06T00:00:00Z;86.95618693993397;3.165161162917604;9.607016197544336;75989331373.41936;24.929152589237855;252114415.5;24.929152589237855 +2022-03-06T00:10:00Z;87.07819373688581;3.124915357416947;9.505936535397085;75985346229.67741;24.933089564499415;252956672;24.933089564499415 +2022-03-06T00:20:00Z;87.22973396392518;3.0042815329698063;9.479026310597702;75981625476.12903;24.936765345254894;252290081;24.936765345254894 +2022-03-06T00:30:00Z;87.17582295690008;3.0792747459257304;9.44254345572853;75977607894.70967;24.940734366119298;249039955.9;24.940734366119298 +2022-03-06T00:40:00Z;87.0019684554672;3.144838269358565;9.565837841461338;75973677452.3871;24.944617301138234;246372484.1;24.944617301138234 +2022-03-06T00:50:00Z;86.95027172897456;3.176412269361941;9.564842993225643;75969830710.55737;24.948417547353177;244249236.6;24.948417547353177 +2022-03-06T01:00:00Z;87.04603899317677;3.0842487043932576;9.591696497420022;75965741056;24.952457770206703;242710990.5;24.952457770206703 +2022-03-06T01:10:00Z;86.89623608122935;3.099153485353498;9.710204610677604;75986689057.03226;24.931762967914988;241218064.5;24.931762967914988 +2022-03-06T01:20:00Z;86.98939833710325;3.1317567715688184;9.584746563628686;76012905042.58064;24.905863855299355;239314217.3;24.905863855299355 +2022-03-06T01:30:00Z;87.16264404771094;3.0832651982694603;9.441642502245728;76006896342.70967;24.91179992794268;238189468.9;24.91179992794268 +2022-03-06T01:40:00Z;87.03186830707739;3.0729953867755095;9.599273790756262;76002502788.12903;24.916140377576248;236669269.3;24.916140377576248 +2022-03-06T01:50:00Z;87.00297646451038;3.0637100209423926;9.63452108045281;75998956023.60655;24.91964427231326;235046251.4;24.91964427231326 +2022-03-06T02:00:00Z;86.7770770510005;3.0418379737430334;9.901223473112529;75994715433.29033;24.923833606563328;232849672.3;24.923833606563328 +2022-03-06T02:10:00Z;86.23847238745283;3.0585671065514988;10.416177516679095;75990976049.54839;24.927527792328977;231666588.9;24.927527792328977 +2022-03-06T02:20:00Z;86.76780895338709;3.094125425163288;9.858806475199788;75986902841.80646;24.93155176715992;230207421.9;24.93155176715992 +2022-03-06T02:30:00Z;86.67156598027545;3.1561614261300073;9.897274268765749;75983023995.87097;24.935383729437923;227798841.8;24.935383729437923 +2022-03-06T02:40:00Z;86.93901402265483;3.1034348672541574;9.678191760944905;75979127180.3871;24.939233444066154;225729569;24.939233444066154 +2022-03-06T02:50:00Z;86.98403508183975;3.055082356549613;9.702439268985271;75975087269.16129;24.943224524836342;221961299.9;24.943224524836342 +2022-03-06T03:00:00Z;86.93497758365294;3.0913803345093585;9.675256310063;75971338374.29507;24.946928106765203;220464425.3;24.946928106765203 +2022-03-06T03:10:00Z;87.1283014821771;3.0343417542790094;9.53083476341674;75989153924.12903;24.92932789369647;253311372.4;24.92932789369647 +2022-03-06T03:20:00Z;86.93496826418894;3.1406769144118565;9.647079858473726;75981307705.80646;24.937079274683768;265369864.3;24.937079274683768 +2022-03-06T03:30:00Z;87.22015253705678;2.9977553922416424;9.523422358594871;75971167265.03226;24.947097147828305;261979631.5;24.947097147828305 +2022-03-06T03:40:00Z;86.81968163932397;3.039897388686091;9.867321965390913;75967574478.45161;24.950646508354318;264726197.7;24.950646508354318 +2022-03-06T03:50:00Z;87.0565654746665;3.029048191669713;9.62339804620906;75963309617.54839;24.954859819832496;265310075.9;24.954859819832496 +2022-03-06T04:00:00Z;87.13481112716973;3.116786797800443;9.467658448237314;75959629924.72131;24.958495036168095;264966815.5;24.958495036168095 +2022-03-06T04:10:00Z;86.42840439711082;3.0429068798631755;10.254474753456279;75955542016;24.9625335342875;263442960.5;24.9625335342875 +2022-03-06T04:20:00Z;86.7762576729987;3.1679265400510044;9.76551907814689;75951687019.35484;24.966341935541823;262328914.6;24.966341935541823 +2022-03-06T04:30:00Z;87.002532264611;3.0359538867932923;9.700449221647549;75947751291.87097;24.970230091840257;260827400.3;24.970230091840257 +2022-03-06T04:40:00Z;86.61481388628117;3.191538646048683;9.918522975228177;75976841216;24.941491777974182;259173409;24.941491777974182 +2022-03-06T04:50:00Z;87.1275271326779;3.0239932582580473;9.581307540767325;75995425494.70967;24.92313212766489;250460226.1;24.92313212766489 +2022-03-06T05:00:00Z;87.04107339928369;3.00057018743617;9.667432326863963;75991298115.14754;24.927209619540598;245487582.4;24.927209619540598 +2022-03-06T05:10:00Z;87.07594257191208;3.2213054124094866;9.365726866692908;75988520557.11476;24.929953605196015;240762417.5;24.929953605196015 +2022-03-06T05:20:00Z;86.90396896300133;3.1339516262729967;9.650417993540001;75984250153.29033;24.934172392598047;242228521.3;24.934172392598047 +2022-03-06T05:30:00Z;87.10806889958111;3.049043225392072;9.565233424002104;75978347024.51613;24.940004170183705;237176435.6;24.940004170183705 +2022-03-06T05:40:00Z;87.09725570790184;3.1429347456655283;9.474281211728433;75973966088.25807;24.94433215401251;233951694.5;24.94433215401251 +2022-03-06T05:50:00Z;86.79749596505906;3.097996192084228;9.827515874588498;75970341656.7742;24.947912776949426;230963860.6;24.947912776949426 +2022-03-06T06:00:00Z;86.86776894023411;3.161171554974272;9.672934119980608;75966188444.90323;24.952015788898542;235917245.9;24.952015788898542 +2022-03-06T06:10:00Z;87.21736239718352;3.0411154822025632;9.470511754369788;75962433133.11476;24.955725710188222;234120328.5;24.955725710188222 +2022-03-06T06:20:00Z;86.88858612332551;3.065594890109778;9.776759048818645;75958405053.93549;24.959705101925994;222442198.7;24.959705101925994 +2022-03-06T06:30:00Z;86.73225847969633;3.1070971616504477;9.85464618412184;75954416474.83871;24.963645471019237;210143958.7;24.963645471019237 +2022-03-06T06:40:00Z;86.68371248167915;3.125272339026229;9.876766005181581;75950599927.74193;24.967415887465332;215021700.1;24.967415887465332 +2022-03-06T06:50:00Z;86.76025225724668;3.0527874006844704;9.813030560635966;75946437598.96774;24.971527906121537;215671246.5;24.971527906121537 +2022-03-06T07:00:00Z;86.84781262553588;3.0226577822682787;9.860569825708179;75942838404.12903;24.97508359744893;216745719.7;24.97508359744893 +2022-03-06T07:10:00Z;87.04976681698157;3.0173141153599574;9.647831359574019;75960544421.16129;24.95759159325758;215543279.5;24.95759159325758 +2022-03-06T07:20:00Z;87.23364751303092;3.033230793268567;9.450882176422121;75957808742.4;24.96029420583677;214190852.2;24.96029420583677 +2022-03-06T07:30:00Z;87.29273116677905;3.0483669028045592;9.371317090369976;75951044475.87097;24.96697671259489;211757980.9;24.96697671259489 +2022-03-06T07:40:00Z;87.21111768492449;3.095634114410143;9.398940752031098;75947304629.67741;24.970671355222482;207350156.4;24.970671355222482 +2022-03-06T07:50:00Z;86.84011292812185;3.0800269728793173;9.777005165747445;75943195416.7742;24.97473090001991;198859412.6;24.97473090001991 +2022-03-06T08:00:00Z;87.27987784097348;3.1252923335161804;9.32037958468154;75939371338.32259;24.978508756789246;226922892.4;24.978508756789246 +2022-03-06T08:10:00Z;86.86945208786499;3.251868049933493;9.59357532774883;75976637010.58064;24.941693515160182;228543058.6;24.941693515160182 +2022-03-06T08:20:00Z;87.21870046756383;3.0813296110283854;9.414312837694359;75986961110.70967;24.931494202553637;226000694.6;24.931494202553637 +2022-03-06T08:30:00Z;87.37979774262631;3.065698321347596;9.260217774017669;75983144859.27869;24.93526432690765;224893498.8;24.93526432690765 +2022-03-06T08:40:00Z;86.5202496675503;3.1052913970890335;10.07405768880446;75979001789.93549;24.93935731892186;225458836.6;24.93935731892186 +2022-03-06T08:50:00Z;87.24016542979813;3.1354721929859264;9.350086378448294;75975359124.64516;24.942955955272982;224526996.6;24.942955955272982 +2022-03-06T09:00:00Z;87.00418146092674;3.053621040468657;9.67013458259969;75971064931.09677;24.94719824485228;223145059.1;24.94719824485228 +2022-03-06T09:10:00Z;87.26697691762007;3.094413461740216;9.361364891545149;75967150938.83871;24.95106492863884;224573836.4;24.95106492863884 +2022-03-06T09:20:00Z;87.23923049815728;3.07086475762353;9.421278653827745;75962829130.32259;24.955334499403424;223672650.3;24.955334499403424 +2022-03-06T09:30:00Z;87.10562688947586;3.0396654364410063;9.57574763342924;75956807310.68852;24.961283533231096;222229640.5;24.961283533231096 +2022-03-06T09:40:00Z;87.09292292353744;3.1129163493428655;9.507298522159816;75952557878.55737;24.96548160242495;221553512.9;24.96548160242495 +2022-03-06T09:50:00Z;87.32654731751107;3.055420938811908;9.343749685198794;75948834155.35484;24.96916031694034;219423182.5;24.96916031694034 +2022-03-06T10:00:00Z;87.10192552574838;3.2303320698610567;9.391814454389172;75940345591.74193;24.977546279182707;216587363.1;24.977546279182707 +2022-03-06T10:10:00Z;87.21373983341846;3.091532005666507;9.416385740615373;75932497986.06451;24.985299030755883;213969556.6;24.985299030755883 +2022-03-06T10:20:00Z;87.09629792020677;3.13662397611556;9.491571024051709;75928635325.93549;24.989115002865454;211775025.5;24.989115002865454 +2022-03-06T10:30:00Z;87.19012697946548;3.0673738696402117;9.486754333068415;75924571565.41936;24.99312964465932;209025618.6;24.99312964465932 +2022-03-06T10:40:00Z;86.9260819130804;3.1078835648548155;9.705263051644735;75920863500.59016;24.996792890064306;235241270.6;24.996792890064306 +2022-03-06T10:50:00Z;87.16159221560348;3.098680793766304;9.468326716241664;75916591976.91803;25.001012783778414;251746634.3;25.001012783778414 +2022-03-06T11:00:00Z;86.11427728789106;3.1619877077336107;10.448263401919101;75913077000.25807;25.004485274873208;250127128.8;25.004485274873208 +2022-03-06T11:10:00Z;86.82446199681355;3.1298305419955814;9.770124504489122;75931713337.80646;24.986074194961006;249178884.2;24.986074194961006 +2022-03-06T11:20:00Z;86.77240415439171;3.1270913196927816;9.832767547691835;75929328805.16129;24.988429905731394;247702108.3;24.988429905731394 +2022-03-06T11:30:00Z;86.85643857575954;3.1786909103220924;9.686993069464176;75922624247.74193;24.995053425084553;245170836.6;24.995053425084553 +2022-03-06T11:40:00Z;87.0977626760898;3.0909578237686643;9.546239986186505;75966441934.45161;24.951765363281375;243725873.5;24.951765363281375 +2022-03-06T11:50:00Z;86.9311266148863;3.1168252467573816;9.659027232679218;75970463307.54099;24.94779259657691;244458793.3;24.94779259657691 +2022-03-06T12:00:00Z;86.94492506066535;3.0824391100235387;9.700165137979795;75966576243.6129;24.95163267751652;246839296;24.95163267751652 +2022-03-06T12:10:00Z;86.90805818273375;3.0840246251112524;9.725398028796146;75962718604.3871;24.955443689410586;245450884.1;24.955443689410586 +2022-03-06T12:20:00Z;86.65657915612422;3.077810531723839;9.996122250717082;75958602520.7742;24.959510021871342;245083421.4;24.959510021871342 +2022-03-06T12:30:00Z;86.895336303443;3.017900393924607;9.822411846163684;75954937723.87097;24.9631305223303;241558693.2;24.9631305223303 +2022-03-06T12:40:00Z;87.03877274423252;3.135636453388127;9.560484854181007;75950682310.19354;24.967334500771393;236985443.1;24.967334500771393 +2022-03-06T12:50:00Z;87.1598682917855;3.040878920185426;9.534089212163929;75947138543.48387;24.97083543393022;235551248.5;24.97083543393022 +2022-03-06T13:00:00Z;87.04523679624941;3.0358629735777267;9.654247059782865;75942808928.5246;24.975112716781386;233832315.9;24.975112716781386 +2022-03-06T13:10:00Z;86.58443942673188;3.0653676318223853;10.076273174620834;75938868917.67741;24.97900510467004;233702234.8;24.97900510467004 +2022-03-06T13:20:00Z;87.07891144697717;3.095632004334188;9.557401736825797;75931553461.67741;24.986232138665336;231286850.1;24.986232138665336 +2022-03-06T13:30:00Z;87.07779917719373;3.0758689787066;9.594675883980534;75920097280;24.99754984933698;230171832.7;24.99754984933698 +2022-03-06T13:40:00Z;86.89451216363331;3.0769213538021103;9.752659896717867;75915961046.70967;25.001636087925753;228968117.7;25.001636087925753 +2022-03-06T13:50:00Z;87.01852692562133;3.0701330621454055;9.637952519281827;75912065882.83871;25.005484170904143;228191793.5;25.005484170904143 +2022-03-06T14:00:00Z;86.89265446038915;3.075109354425754;9.765204994841026;75908202697.44263;25.009300661931867;226254914.1;25.009300661931867 +2022-03-06T14:10:00Z;87.08385692796438;3.084399858515035;9.559554173377368;75904098572.59016;25.013355180177843;225621289.3;25.013355180177843 +2022-03-06T14:20:00Z;87.0121694387828;3.0832272133537777;9.630487235942406;75900412828.90323;25.016996374236484;223714271;25.016996374236484 +2022-03-06T14:30:00Z;87.04737857401922;3.001079486217972;9.704120158951866;75896209143.74193;25.02114924940465;222287099.8;25.02114924940465 +2022-03-06T14:40:00Z;86.86610717568688;3.0518349742773294;9.810603162877806;75892653022.96774;25.024662387304257;221361317.2;25.024662387304257 +2022-03-06T14:50:00Z;86.8254134809278;3.0657317935967816;9.8415318611958;75886987858.58064;25.030259076781245;220220184.8;25.030259076781245 +2022-03-06T15:00:00Z;86.94835963964732;3.077213337137432;9.697465757621341;75868017498.83871;25.049000141556718;217678154.3;25.049000141556718 +2022-03-06T15:10:00Z;86.72797236194859;3.1401329665443116;9.848818784118516;75941273122.13333;24.976629959862308;215341386.3;24.976629959862308 +2022-03-06T15:20:00Z;86.7084331431429;3.064845674656457;9.965778602562432;75938356190.96774;24.979511634045814;212351438.5;24.979511634045814 +2022-03-06T15:30:00Z;86.90261145551038;3.0583390315855428;9.761990274328117;75931830139.87097;24.985958804684437;210480557.4;24.985958804684437 +2022-03-06T15:40:00Z;87.10966523419737;3.1116609719241106;9.505588571060805;75927890184.25807;24.989851138006447;210009104.8;24.989851138006447 +2022-03-06T15:50:00Z;86.78282174845984;3.186585397936308;9.720573418349435;75923945604.12903;24.99374803994801;207780038.2;24.99374803994801 +2022-03-06T16:00:00Z;86.98900664701434;3.0231110357264934;9.72094108799659;75919907344.51613;24.997737489068378;205725960.3;24.997737489068378 +2022-03-06T16:10:00Z;87.17126141138736;3.1276231322;9.424429516274534;75916156267.35484;25.00144322691487;202804124.9;25.00144322691487 +2022-03-06T16:20:00Z;87.07499105217661;3.1068324757560806;9.573302477535789;75911945635.67213;25.005602964641774;201064117.7;25.005602964641774 +2022-03-06T16:30:00Z;86.82212218423682;3.0855896946147805;9.797356602098121;75908381596.90323;25.00912392483119;199104049.5;25.00912392483119 +2022-03-06T16:40:00Z;86.83004419794665;3.053319495480556;9.832653341704708;75904083769.80646;25.01336980404013;198000707.1;25.01336980404013 +2022-03-06T16:50:00Z;87.18221900201455;3.0609413285040765;9.49721788247395;75900570921.29033;25.016840192713982;195976026.8;25.016840192713982 +2022-03-06T17:00:00Z;86.84850013017231;3.0871251259480856;9.779869977979027;75896300577.03226;25.021058921269624;194699792.5;25.021058921269624 +2022-03-06T17:10:00Z;86.52779737790134;3.2212739771299908;9.957975124717178;75912333444.12903;25.005219843630346;192477448.3;25.005219843630346 +2022-03-06T17:20:00Z;87.3155356985173;3.0215502964328684;9.388335182285621;75908903382.03279;25.008608446524775;190363449.8;25.008608446524775 +2022-03-06T17:30:00Z;87.18592049558193;3.1314806353994897;9.419237515160045;75902566267.87097;25.014868963911468;189060855.7;25.014868963911468 +2022-03-06T17:40:00Z;86.53608925284637;3.064360018094398;10.128492693094582;75898544194.06451;25.01884242286341;208786079.5;25.01884242286341 +2022-03-06T17:50:00Z;87.17682349121092;3.0309175648334166;9.54363744439411;75890085888;25.02719849328076;212916794.8;25.02719849328076 +2022-03-06T18:00:00Z;87.71637881814051;3.076237859217254;8.945326435960453;75882439448.7742;25.034752509903637;211316339.6;25.034752509903637 +2022-03-06T18:10:00Z;87.73449493461479;3.0139541597796753;8.997108990966522;75878321317.16129;25.03882086561019;234616237.4;25.03882086561019 +2022-03-06T18:20:00Z;87.80025599462274;3.009688017395506;8.92356296092957;75874756608;25.042342488088945;255463424;25.042342488088945 +2022-03-06T18:30:00Z;87.29465481930639;3.047059608592493;9.352652846336532;75876343002.2295;25.040775268625577;254770076.9;25.040775268625577 +2022-03-06T18:40:00Z;87.60855829202747;2.9754050556806826;9.153382159740094;75926222121.29033;24.991499039077024;253610776.8;24.991499039077024 +2022-03-06T18:50:00Z;87.54324896591156;3.1318382496115373;9.072032964807418;75921992869.16129;24.995677172184692;252074420.5;24.995677172184692 +2022-03-06T19:00:00Z;87.64384859701232;3.0932421991631314;8.998347725007132;75918371873.03226;24.999254401289942;249868023.7;24.999254401289942 +2022-03-06T19:10:00Z;87.40609960625144;3.0175536279261195;9.289324972982383;75936230829.41936;24.981611306323583;247877433.8;24.981611306323583 +2022-03-06T19:20:00Z;87.15613840849392;2.9769011973124773;9.60875411754443;75933199128.7742;24.98460636276657;246693755.9;24.98460636276657 +2022-03-06T19:30:00Z;87.4337028495817;3.0551335157252675;9.24624047816672;75926885805.41936;24.990843376906042;244644566.7;24.990843376906042 +2022-03-06T19:40:00Z;87.66318891862177;3.1170628651149124;8.972785221110481;75922904181.5082;24.994776874881083;242667652.1;24.994776874881083 +2022-03-06T19:50:00Z;86.60207792009639;3.129484676940518;10.013079389247375;75919184466.58064;24.998451629569548;242105562.2;24.998451629569548 +2022-03-06T20:00:00Z;87.34670443638132;3.019585772447481;9.393784771203837;75915116742.19354;25.00247018732304;241199070.4;25.00247018732304 +2022-03-06T20:10:00Z;87.00688518218242;3.0754106736091664;9.632492175923687;75911512460.3871;25.00603090413192;238864978.6;25.00603090413192 +2022-03-06T20:20:00Z;87.46087961609176;3.011572991082529;9.280571587115652;75907288559.48387;25.010203750694114;236858929.5;25.010203750694114 +2022-03-06T20:30:00Z;87.46371196710653;2.9685325861024157;9.284679003663118;75903829883.87097;25.013620621253267;236004649.3;25.013620621253267 +2022-03-06T20:40:00Z;87.48188775889511;2.9956000112514753;9.258042594738601;75899587735.08197;25.01781149513881;234994456.8;25.01781149513881 +2022-03-06T20:50:00Z;87.23472672835216;3.045895785534226;9.465523784891818;75895986612.45901;25.021369090949282;232514791.2;25.021369090949282 +2022-03-06T21:00:00Z;87.54261675065287;3.023050688019394;9.174851685391483;75891921292.3871;25.025385273448563;231769205.5;25.025385273448563 +2022-03-06T21:10:00Z;87.8037459812697;3.009727795940902;8.926030378616137;75887761738.32259;25.02949455093306;229358889.3;25.02949455093306 +2022-03-06T21:20:00Z;87.80811832919885;3.0383848098722797;8.88881906643878;75883791789.41936;25.033416515016135;227500098.1;25.033416515016135 +2022-03-06T21:30:00Z;87.79877594219452;3.028896644498322;8.914192945343096;75877455607.74193;25.039676111189365;227006464;25.039676111189365 +2022-03-06T21:40:00Z;87.7337529142495;2.950827341136902;9.070013597862792;75873596713.29033;25.04348836313731;224796936.3;25.04348836313731 +2022-03-06T21:50:00Z;87.69826881954448;3.028510579265477;9.016590551272898;75869540150.55737;25.047495894147698;222399587.1;25.047495894147698 +2022-03-06T22:00:00Z;87.69008844794566;3.0566258374563673;8.999323179140479;75866814464;25.05018863529886;218257936.5;25.05018863529886 +2022-03-06T22:10:00Z;87.4026920852698;3.039106336573424;9.291057181145577;75917117440;25.000493671975047;231712801.6;25.000493671975047 +2022-03-06T22:20:00Z;87.40007725178744;3.0903497880341884;9.212340995339149;75913670986.32259;25.003898468325392;236840167.2;25.003898468325392 +2022-03-06T22:30:00Z;87.88424186368383;3.054624889464871;8.797700864526789;75909415506.58064;25.008102512032483;235267105;25.008102512032483 +2022-03-06T22:40:00Z;87.68208995569094;3.06158187526291;9.0060905883396;75905852052.64516;25.011622894457368;234525134.5;25.011622894457368 +2022-03-06T22:50:00Z;87.8026571625497;3.0322721674492628;8.901408086316534;75901712119.74193;25.01571278794179;232033379.1;25.01571278794179 +2022-03-06T23:00:00Z;87.86316951281509;3.05057658556909;8.834974808963736;75898000568.65573;25.01937947746534;231103521;25.01937947746534 +2022-03-06T23:10:00Z;87.56806683386465;3.0732449361799983;9.033001287615772;75923222858.32259;24.99446204991719;229060138;24.99446204991719 +2022-03-06T23:20:00Z;87.82345266009196;3.0379513813638206;8.882983993541211;75920213949.93549;24.997434589592412;227324168.3;24.997434589592412 +2022-03-06T23:30:00Z;87.53812999257036;2.9886065710026735;9.18556817321441;75913952024.7742;25.003620826788925;226127475.6;25.003620826788925 +2022-03-06T23:40:00Z;87.49786627450082;3.023243910999273;9.221986095480155;75909840367.48387;25.007682786428106;224610766.5;25.007682786428106 +2022-03-06T23:50:00Z;87.60004060186158;3.0055477414237144;9.129567497120135;75906202657.03226;25.011276527829725;223578442.3;25.011276527829725 +2022-03-07T00:00:00Z;87.9012761213904;3.0026102772178858;8.847052207913947;75899301161.29033;25.01809460510958;222766971.9;25.01809460510958 +2022-03-07T00:10:00Z;87.89793273663705;3.007578085612051;8.836419599938246;75890169889.57378;25.027115507035024;221317252.1;25.027115507035024 +2022-03-07T00:20:00Z;87.3387422242276;3.052405570513487;9.348174532066295;75917658640.51613;24.99995901295607;219126733.6;24.99995901295607 +2022-03-07T00:30:00Z;87.830147400544;2.968524270534409;8.929440896144333;75914136080.51613;25.003438995730956;217632701.9;25.003438995730956 +2022-03-07T00:40:00Z;87.3634668494298;3.016333359230588;9.354091523110293;75909996940.3871;25.00752810602345;215530595.1;25.00752810602345 +2022-03-07T00:50:00Z;87.90260263642212;2.9843366564799005;8.8338508297608;75906274667.35484;25.011205387896773;214540023.7;25.011205387896773 +2022-03-07T01:00:00Z;87.89324616192263;2.962525115174141;8.860476548233349;75902308285.93549;25.01512382761619;212362537.3;25.01512382761619 +2022-03-07T01:10:00Z;87.9233628002311;2.9419241459248147;8.859516091675072;75898003993.18033;25.019376094333026;209603418.8;25.019376094333026 +2022-03-07T01:20:00Z;88.07600427028207;2.9940322529206487;8.663522992231519;75894153017.80646;25.023180522921212;208129712.3;25.023180522921212 +2022-03-07T01:30:00Z;88.10072643719437;3.009487270085523;8.614870512434175;75887696862.96774;25.02955864213871;206204928;25.02955864213871 +2022-03-07T01:40:00Z;88.1123733118434;2.926359645240232;8.718464300035143;75883980866.06451;25.03322972374265;226326594.1;25.03322972374265 +2022-03-07T01:50:00Z;87.83183257093964;3.0177964937342527;8.872189089938987;75879788610.06451;25.037371307893935;251082685.9;25.037371307893935 +2022-03-07T02:00:00Z;87.70293808741057;3.0703920338035253;8.964067582032976;75876308925.93549;25.04080893303903;250628029.9;25.04080893303903 +2022-03-07T02:10:00Z;87.9542575392255;3.023539250331862;8.741389758603807;75872049454.16394;25.04501692052403;248859548.9;25.04501692052403 +2022-03-07T02:20:00Z;87.86689143948068;2.981342647962892;8.874639982976802;75868513445.16129;25.0485101897433;246587193.8;25.0485101897433 +2022-03-07T02:30:00Z;87.73257452803377;3.0105386422980973;9.010602209630285;75864337639.2258;25.052635522662204;244498773.3;25.052635522662204 +2022-03-07T02:40:00Z;87.74605521563078;3.038731465483897;8.938824219872865;75860663064.7742;25.056265682488213;244053751.7;25.056265682488213 +2022-03-07T02:50:00Z;87.93208276253462;3.0352550978906985;8.744576894740938;75856647201.03226;25.060233006436768;242529313;25.060233006436768 +2022-03-07T03:00:00Z;87.9873296548905;3.101244068216285;8.639589633675504;75852821272.7742;25.064012690653946;241030903.7;25.064012690653946 +2022-03-07T03:10:00Z;87.86536198584882;3.0651151436608925;8.785224105527197;75870752834.06451;25.04629786836071;239744297.3;25.04629786836071 +2022-03-07T03:20:00Z;87.87140857325865;2.991382022500467;8.861240293376275;75867469857.57378;25.049541163475098;237601032.3;25.049541163475098 +2022-03-07T03:30:00Z;87.5938738353832;3.0344276855643817;9.093843884015394;75861388122.83871;25.055549388209236;235333799.9;25.055549388209236 +2022-03-07T03:40:00Z;88.00256349770957;3.0851309246036367;8.66693198918036;75907501485.41936;25.00999339839697;234152808.9;25.00999339839697 +2022-03-07T03:50:00Z;87.82886722516075;3.0065684053451673;8.880283926608271;75909365627.87097;25.008151787857603;232330405.2;25.008151787857603 +2022-03-07T04:00:00Z;87.96549702876874;3.0246753170303897;8.715669977600664;75905085572.12903;25.012380110514282;229820812.4;25.012380110514282 +2022-03-07T04:10:00Z;88.12714128452097;2.9689693683192107;8.625589064185158;75901636541.93549;25.01578745223837;228173031.2;25.01578745223837 +2022-03-07T04:20:00Z;88.05506886207911;2.981579549722548;8.687325341584964;75898114576.51613;25.019266847619328;225125012.6;25.019266847619328 +2022-03-07T04:30:00Z;88.10357316492284;3.018279781158236;8.584420572677422;75894487207.86885;25.02285037221812;224730673.5;25.02285037221812 +2022-03-07T04:40:00Z;87.21707336325083;3.063583479160509;9.442239365487898;75890445477.16129;25.02684325047799;223169217;25.02684325047799 +2022-03-07T04:50:00Z;87.70165166442352;3.0580879932870166;8.980918215656807;75886670088.25807;25.03057300621012;221297895.2;25.03057300621012 +2022-03-07T05:00:00Z;87.32666139297527;3.044453175976002;9.368607566637262;75882764354.06451;25.034431531747472;219494664.3;25.034431531747472 +2022-03-07T05:10:00Z;88.0379048514714;2.969045735739132;8.722574807212862;75879706624;25.03745230299191;218252783.5;25.03745230299191 +2022-03-07T05:20:00Z;87.96168580009378;3.0525801974942586;8.694865567178299;75875995714.06451;25.041118359114343;216732176.5;25.041118359114343 +2022-03-07T05:30:00Z;87.92869422542236;3.0247009279943855;8.773539229062019;75866072987.27869;25.05092114978212;217710459.9;25.05092114978212 +2022-03-07T05:40:00Z;87.98471198979684;3.0384548332636956;8.703117474044243;75857434690.06451;25.059455035793917;217882691.1;25.059455035793917 +2022-03-07T05:50:00Z;88.06743486371468;2.9856463757730474;8.675575750780656;75853162363.87097;25.063675722329354;216692207.5;25.063675722329354 +2022-03-07T06:00:00Z;87.96128594733685;3.0490725293660823;8.718409113195444;75849730246.19354;25.06706635595911;215776751.5;25.06706635595911 +2022-03-07T06:10:00Z;87.80844888132512;2.936330792998716;8.964294729144479;75845463006.96774;25.071282017013054;214512871.2;25.071282017013054 +2022-03-07T06:20:00Z;87.631331449898;2.9653533781555392;9.106384874231237;75841899883.35484;25.074802073107968;214872394.3;25.074802073107968 +2022-03-07T06:30:00Z;87.82398358912486;3.0107284191291734;8.884678000832109;75837781421.41936;25.07887075514449;213625955.1;25.07887075514449 +2022-03-07T06:40:00Z;87.35303941228774;3.0045008299983693;9.379826581812605;75834023341.41936;25.082583411186313;211992849.1;25.082583411186313 +2022-03-07T06:50:00Z;88.054384121137;3.0527922673480155;8.617458734545778;75830078827.35484;25.08648024786187;209949596.9;25.08648024786187 +2022-03-07T07:00:00Z;87.64746471555516;3.0699316475984597;8.98371630103651;75826159748.12903;25.090351957129904;207562289.5;25.090351957129904 +2022-03-07T07:10:00Z;87.18028061959252;3.0816941150289;9.443740110984416;75890006610.58064;25.027276812472994;206808031;25.027276812472994 +2022-03-07T07:20:00Z;87.7259839499752;3.032062531269092;8.951527632503565;75896536229.16129;25.0208261174707;207178454.7;25.0208261174707 +2022-03-07T07:30:00Z;87.96562048858243;3.0009236556322048;8.756423801734272;75890465405.90164;25.026823562616574;205086854.3;25.026823562616574 +2022-03-07T07:40:00Z;87.84491432754227;3.063034455273097;8.80342348764852;75886098167.74193;25.031138013916088;203479172.1;25.031138013916088 +2022-03-07T07:50:00Z;87.66669849925293;3.172735652881856;8.88237035513586;75882581751.74193;25.034611926953588;201597786.8;25.034611926953588 +2022-03-07T08:00:00Z;87.94748323266177;3.0640548583669567;8.679062472783967;75878271108.12903;25.03887046776526;201065637.2;25.03887046776526 +2022-03-07T08:10:00Z;87.9515986888372;3.031608951208815;8.736655385315567;75874691930.83871;25.042406383496612;201299968;25.042406383496612 +2022-03-07T08:20:00Z;87.72894917906586;3.177942108299969;8.81176587905279;75870499476.64516;25.04654816344588;209004913.3;25.04654816344588 +2022-03-07T08:30:00Z;87.75694985927616;3.044558360160077;8.925773843420764;75866508981.67741;25.050490425252928;206382839.7;25.050490425252928 +2022-03-07T08:40:00Z;87.61897913571487;2.980529944623486;9.132609611684408;75862898824.53334;25.05405694638417;204165120;25.05405694638417 +2022-03-07T08:50:00Z;86.96396244499888;3.0915783605282594;9.647302108319142;75858574897.54839;25.05832861001163;203030726.2;25.05832861001163 +2022-03-07T09:00:00Z;87.63750744311955;3.013799117930136;9.070802971830322;75855048968.25807;25.061811921352188;205103368.3;25.061811921352188 +2022-03-07T09:10:00Z;87.89778800885865;3.1007560315500986;8.713401992648992;75850324826.83871;25.066478962017367;221397322.3;25.066478962017367 +2022-03-07T09:20:00Z;87.8765547568617;3.033379823789265;8.822985676667725;75846636709.16129;25.070122501372037;248666310.2;25.070122501372037 +2022-03-07T09:30:00Z;87.94758222738704;3.007081039037414;8.75673447418285;75840082514.58064;25.07659747532392;247507581.9;25.07659747532392 +2022-03-07T09:40:00Z;87.89292718500447;3.0321550689509142;8.81300074609589;75836175678.95082;25.08045708898448;246549999.5;25.08045708898448 +2022-03-07T09:50:00Z;87.69099080868712;3.113549312656496;8.896864081922564;75832142999.08197;25.084441025803237;244760311.7;25.084441025803237 +2022-03-07T10:00:00Z;87.93145468947691;3.1339678929829593;8.663751756141659;75828201736.25807;25.088334650535952;243025589.7;25.088334650535952 +2022-03-07T10:10:00Z;87.53970656508955;3.134012967708826;9.003418412916623;75817129389.41936;25.09927316578521;241640745.3;25.09927316578521 +2022-03-07T10:20:00Z;86.79387865475061;3.1357257038757997;9.716524055928952;75812736231.2258;25.103613223822812;239918773.7;25.103613223822812 +2022-03-07T10:30:00Z;87.76362720564231;3.0542782985733994;8.882078392950616;75806974546.58064;25.10930526691633;239052363.5;25.10930526691633 +2022-03-07T10:40:00Z;87.76560088433797;3.1169030211038127;8.837908068351318;75857080716.3871;25.059804730987253;236034642.6;25.059804730987253 +2022-03-07T10:50:00Z;87.8327647110396;2.9884410121028364;8.899602946511985;75854726060.06557;25.06213092654947;235232355.1;25.06213092654947 +2022-03-07T11:00:00Z;87.90515979771837;3.0690303301481014;8.741179382662612;75850813968.51613;25.065995732601287;234448829.9;25.065995732601287 +2022-03-07T11:10:00Z;87.07227601941267;3.130195707445535;9.493687466898807;75880353065.29033;25.03681367524523;232305300.6;25.03681367524523 +2022-03-07T11:20:00Z;87.93989305813668;3.038238718003823;8.751302757088485;75878245541.16129;25.038895725704762;230730322.6;25.038895725704762 +2022-03-07T11:30:00Z;87.87548330692321;3.0525006009444295;8.79632255637498;75871498240;25.045561472155722;228190141.9;25.045561472155722 +2022-03-07T11:40:00Z;87.40235403633763;3.1263533281753326;9.184963236179337;75868968365.41936;25.048060768111867;226976836.3;25.048060768111867 +2022-03-07T11:50:00Z;87.11742153822284;3.2854230030414207;9.269154851799373;75863698332.90323;25.053267101681577;229086637.4;25.053267101681577 +2022-03-07T12:00:00Z;87.50380266738159;3.0313972204842963;9.159895614872909;75859836525.11476;25.057082231752833;250685968.5;25.057082231752833 +2022-03-07T12:10:00Z;87.49403503798654;3.0650995478091674;9.147517980266457;75855826085.16129;25.061044197470327;249726909.9;25.061044197470327 +2022-03-07T12:20:00Z;87.7606405506057;3.065897169389486;8.88775471643404;75851882562.06451;25.064940055155972;248592053.7;25.064940055155972 +2022-03-07T12:30:00Z;87.71521434930102;3.125183167561315;8.872630537194437;75847917369.80646;25.06885732008751;248088245.7;25.06885732008751 +2022-03-07T12:40:00Z;87.75293001865121;3.1134914833664804;8.859568230295618;75844459949.41936;25.07227295059279;245917998.2;25.07227295059279 +2022-03-07T12:50:00Z;87.66639156046509;3.027162448521382;9.029830736580893;75841053464.7742;25.075638261017048;243981060.2;25.075638261017048 +2022-03-07T13:00:00Z;87.70765637915017;3.071088424312845;8.93088697824281;75837244449.03226;25.079401237139887;244078658.1;25.079401237139887 +2022-03-07T13:10:00Z;87.32277528951595;3.084360354831244;9.299421023708787;75832695959.08197;25.08389474943741;243335101.9;25.08389474943741 +2022-03-07T13:20:00Z;87.73713589253529;3.074200677094038;8.88907462009265;75828774912;25.087768402776124;242451819.4;25.087768402776124 +2022-03-07T13:30:00Z;87.67994177906168;3.178039872666646;8.866090683691572;75822528908.3871;25.093938910868204;241123856.5;25.093938910868204 +2022-03-07T13:40:00Z;87.66764450049371;3.0157234752255637;9.043822127260839;75818355877.16129;25.09806150261536;238616047.5;25.09806150261536 +2022-03-07T13:50:00Z;87.41429185410773;3.016827742833531;9.295705860066578;75814433296.51613;25.101936670981072;238948217.7;25.101936670981072 +2022-03-07T14:00:00Z;87.47643471951146;2.974065190014335;9.227047598183319;75816941501.93549;25.099458782270794;237438183.2;25.099458782270794 +2022-03-07T14:10:00Z;87.89944214379875;3.0946544397571434;8.724656425328243;75862284724.45901;25.054663623823508;235000534.7;25.054663623823508 +2022-03-07T14:20:00Z;87.87571057844848;3.118255980964746;8.727339774003749;75858336074.32259;25.058564546578236;229284038.2;25.058564546578236 +2022-03-07T14:30:00Z;87.9529359337322;3.0834913693340944;8.679114699264298;75854601843.6129;25.06225364159639;228313814.7;25.06225364159639 +2022-03-07T14:40:00Z;88.16772259435443;2.9414682843239834;8.621654738820963;75850503729.54839;25.066302221706888;227144406.7;25.066302221706888 +2022-03-07T14:50:00Z;88.08708205140262;3.0036266853483644;8.624539393941042;75846618541.41936;25.07014044952026;227037910.7;25.07014044952026 +2022-03-07T15:00:00Z;87.81868750260278;3.0583203211069767;8.83648760361057;75842787129.80646;25.073925550814895;225360644.2;25.073925550814895 +2022-03-07T15:10:00Z;87.80378192819285;3.055026235069228;8.869246814369077;75860683121.31148;25.056245868374535;224002378.3;25.056245868374535 +2022-03-07T15:20:00Z;87.41730590109539;3.142810054677675;9.16201371188245;75857835107.09677;25.059059458607152;222395359;25.059059458607152 +2022-03-07T15:30:00Z;86.99229471622371;3.071055213914423;9.653122320225615;75851266906.83871;25.06554826894967;220486887.2;25.06554826894967 +2022-03-07T15:40:00Z;87.88866006052817;3.0266560608944326;8.804378307172477;75847251901.93549;25.069514744440305;218077976.8;25.069514744440305 +2022-03-07T15:50:00Z;87.79435042428494;3.1453344820401123;8.793514042844889;75843482392.7742;25.073238691499018;216196657.5;25.073238691499018 +2022-03-07T16:00:00Z;88.04935429996458;3.006587952265131;8.671200303826271;75839494276.12903;25.077178603730296;215452487.3;25.077178603730296 +2022-03-07T16:10:00Z;87.94671294963946;3.0726976942078092;8.701947029695962;75835403429.16129;25.081220004581525;213473380.7;25.081220004581525 +2022-03-07T16:20:00Z;87.6870321142969;3.0693675227531187;8.95713279670959;75831790250.66667;25.084789510544205;211782821.2;25.084789510544205 +2022-03-07T16:30:00Z;87.8130443279695;3.055271017720531;8.844518418979083;75827569895.2258;25.088958854498067;209453056;25.088958854498067 +2022-03-07T16:40:00Z;87.95473007577533;2.983072249406729;8.776042295194692;75823805539.09677;25.092677710809276;222307955.6;25.092677710809276 +2022-03-07T16:50:00Z;87.45228336714182;3.0487353080853876;9.227191964118884;75819870670.45161;25.096565018649777;255553073.5;25.096565018649777 +2022-03-07T17:00:00Z;87.7527718240657;3.0038352687602776;8.958936399838148;75815726773.67741;25.100658828093795;253958870.7;25.100658828093795 +2022-03-07T17:10:00Z;87.901628210851;3.088614931547823;8.720921613477989;75813032134.19354;25.1033208974378;252447760.8;25.1033208974378 +2022-03-07T17:20:00Z;87.86673878839196;3.044155738783692;8.798200898947997;75808892597.67741;25.107410399326255;250863280.3;25.107410399326255 +2022-03-07T17:30:00Z;87.9024889814449;3.075132583880521;8.75149846897401;75810629867.01639;25.105694128382684;249012025.8;25.105694128382684 +2022-03-07T17:40:00Z;87.42373846148345;2.995555179099766;9.282830248133434;75845955914.32259;25.07079506743534;247283117.4;25.07079506743534 +2022-03-07T17:50:00Z;87.72534699375223;3.161869427000571;8.854394858424643;75834062187.35484;25.082545034782115;245587968;25.082545034782115 +2022-03-07T18:00:00Z;87.80296299893065;3.1229681087289496;8.787891893447988;75829849583.48387;25.086706720859407;243768287;25.086706720859407 +2022-03-07T18:10:00Z;87.81863388814243;3.0460713501074155;8.85171586609498;75825682365.93549;25.09082356919914;241737001.3;25.09082356919914 +2022-03-07T18:20:00Z;87.46284600092007;3.1059343060981766;9.168826157317351;75821808606.96774;25.094650505995627;240468975.2;25.094650505995627 +2022-03-07T18:30:00Z;87.5463884289798;3.0390466103143052;9.146648094942586;75817941495.60655;25.098470875535263;242000202.3;25.098470875535263 +2022-03-07T18:40:00Z;87.69538445738023;3.0978500025796065;8.932583269347905;75813901038.93333;25.10246249516006;240741607.2;25.10246249516006 +2022-03-07T18:50:00Z;87.68670253478548;3.175368249978028;8.85940053220495;75810186933.67741;25.106131707981056;240526699.4;25.106131707981056 +2022-03-07T19:00:00Z;87.74249880746316;3.06667989017751;8.906049604349386;75805989392.51613;25.110278513411817;240209325.4;25.110278513411817 +2022-03-07T19:10:00Z;87.66762756953295;3.1318775967312193;8.908585417143255;75824015029.67741;25.092470752343797;240935176.3;25.092470752343797 +2022-03-07T19:20:00Z;87.82975399933972;3.158746117002529;8.735672930307404;75820823122.58064;25.095624078821086;240791684.1;25.095624078821086 +2022-03-07T19:30:00Z;87.77950186144339;3.063210440437689;8.877748064856238;75814816404.64516;25.1015581934846;239778429.9;25.1015581934846 +2022-03-07T19:40:00Z;87.80934617417846;3.0076453533407426;8.881717468388143;75810492348.85246;25.105829984362924;238713823;25.105829984362924 +2022-03-07T19:50:00Z;87.2554463989598;3.104922726769179;9.342846172084714;75806754089.29033;25.10952305953674;236447413.7;25.10952305953674 +2022-03-07T20:00:00Z;87.72778267037573;3.025499616807568;8.938527165508377;75802747276.3871;25.11348144204419;232926439.2;25.11348144204419 +2022-03-07T20:10:00Z;87.69227555377037;3.079384567936435;8.951774808572997;75798794107.87097;25.117386828564896;230181987.1;25.117386828564896 +2022-03-07T20:20:00Z;87.13464353769673;3.1025970592214844;9.474776815757604;75794947171.09677;25.121187267368015;229313899.4;25.121187267368015 +2022-03-07T20:30:00Z;87.91390468251358;2.934664529533348;8.87037299982821;75790854210.06451;25.125230756731032;229639621.2;25.125230756731032 +2022-03-07T20:40:00Z;87.74050260579487;3.105885413552506;8.861249772706257;75787176775.34427;25.12886374225358;227147049.3;25.12886374225358 +2022-03-07T20:50:00Z;88.02877460628174;2.9916336891901465;8.687300612883938;75782879467.01639;25.133109108963968;226275460.1;25.133109108963968 +2022-03-07T21:00:00Z;87.85666269379621;3.0613596357675603;8.789580789372721;75800948736;25.115258243451983;225934435.1;25.115258243451983 +2022-03-07T21:10:00Z;87.9137246061688;3.0313395931042977;8.77708439195821;75830337205.67741;25.08622499256118;223648717.6;25.08622499256118 +2022-03-07T21:20:00Z;87.91688251880224;3.071129969163848;8.743610948720372;75826750761.29033;25.089768087551803;222068141.4;25.089768087551803 +2022-03-07T21:30:00Z;87.83596653369558;3.1090234352846693;8.760064056988416;75819957743.48387;25.096478998070296;220232803.1;25.096478998070296 +2022-03-07T21:40:00Z;88.06021797197327;3.037278660119193;8.627517312584448;75816142451.6129;25.100248174462518;218046992.5;25.100248174462518 +2022-03-07T21:50:00Z;87.78458189503735;3.0388200839586155;8.907524731111499;75812103889.83606;25.10423792209456;215801459.6;25.10423792209456 +2022-03-07T22:00:00Z;87.60135860108491;3.049347877537451;9.056738367071734;75808201562.83871;25.108093081618545;214030071.7;25.108093081618545 +2022-03-07T22:10:00Z;87.43229180642587;3.102608860783772;9.206240475738586;75804310494.96774;25.111937118105335;212496585.4;25.111937118105335 +2022-03-07T22:20:00Z;87.94114197694135;3.0480575700533667;8.750468054060116;75800260674.06451;25.11593798877458;210532021.7;25.11593798877458 +2022-03-07T22:30:00Z;87.88031019485223;3.0324910195239454;8.810585414099629;75796530076.90323;25.119623494163086;208937356.4;25.119623494163086 +2022-03-07T22:40:00Z;87.98124208704238;3.0308848409566505;8.710679443450731;75792319653.16129;25.12378302646259;206732519.2;25.12378302646259 +2022-03-07T22:50:00Z;87.89973572775372;2.8902910252094394;8.93673529587993;75788760823.74193;25.12729884026794;207130690.1;25.12729884026794 +2022-03-07T23:00:00Z;87.9769046975052;3.0412622886117497;8.702177202061957;75784431582.42622;25.131575753991775;204899361;25.131575753991775 +2022-03-07T23:10:00Z;87.88529653369072;3.0433665816038293;8.74647175364029;75809967137.03226;25.106348847941522;202317691.9;25.106348847941522 +2022-03-07T23:20:00Z;87.45573292747038;3.0887184564073435;9.170178374434865;75806592627.6129;25.10968256962493;200745984;25.10968256962493 +2022-03-07T23:30:00Z;87.57897127927998;3.0248480962355133;9.098797284575245;75800444465.54839;25.11575641878058;199342278.2;25.11575641878058 +2022-03-07T23:40:00Z;87.92156233198449;3.055278563222251;8.748088783427088;75796283259.87097;25.119867327914907;196794434.1;25.119867327914907 +2022-03-07T23:50:00Z;87.78253821128737;3.0473277919222936;8.898353081473074;75792427470.45161;25.123676512361154;195266493.9;25.123676512361154 +2022-03-08T00:00:00Z;87.91359913861112;3.0647141122059853;8.734367505699115;75788505220.12903;25.127551354396896;193152363.4;25.127551354396896 +2022-03-08T00:10:00Z;88.04860555444132;3.0033412812833213;8.663594430387002;75784639538.36066;25.131370311623233;198774189.4;25.131370311623233 +2022-03-08T00:20:00Z;86.84665557392702;3.138979368154379;9.726991228702534;75780958406.19354;25.135006949901527;236962060.6;25.135006949901527 +2022-03-08T00:30:00Z;87.7874888903808;3.116344850961931;8.797819218087064;75806423040;25.10985010743031;237265164.6;25.10985010743031 +2022-03-08T00:40:00Z;88.00866480011402;3.0092975721406345;8.691922741729499;75828874801.54839;25.087669720593897;242219734.7;25.087669720593897 +2022-03-08T00:50:00Z;87.59773610291961;3.052455621277338;9.071801597881576;75824546584.7742;25.09194562215987;242717663;25.09194562215987 +2022-03-08T01:00:00Z;87.62107913423722;3.0326904649173256;9.08236761283617;75817417562.83871;25.098988475521434;240308224;25.098988475521434 +2022-03-08T01:10:00Z;87.86044684318826;3.0188844020033025;8.826441842315223;75807948800;25.10834278930978;236336227.1;25.10834278930978 +2022-03-08T01:20:00Z;87.87378451094104;3.0343943329132967;8.815540650569305;75804280237.41936;25.111967009930375;234219321.8;25.111967009930375 +2022-03-08T01:30:00Z;87.63397289486504;3.081822984551695;9.005594327075473;75797697370.83871;25.118470309323452;233530572.8;25.118470309323452 +2022-03-08T01:40:00Z;87.99445796356754;3.010421991096735;8.725405970037434;75793803858.58064;25.122316760652005;231360181.7;25.122316760652005 +2022-03-08T01:50:00Z;87.71539862776255;3.1674213780718548;8.715309259205355;75789833843.6129;25.126238790001064;230458136.8;25.126238790001064 +2022-03-08T02:00:00Z;87.8826990110845;3.136702716688631;8.705057552210203;75785869774.45161;25.130154945410702;229009738.3;25.130154945410702 +2022-03-08T02:10:00Z;87.99491087428379;3.04420542370312;8.67930388187116;75782059635.6129;25.13391903105542;227096113.5;25.13391903105542 +2022-03-08T02:20:00Z;87.92745581624776;3.012275441970928;8.77659411840266;75777903684.26666;25.13802474936773;225088677.2;25.13802474936773 +2022-03-08T02:30:00Z;87.4316833445512;3.0080664521055067;9.279046008063196;75774275980.3871;25.14160860514686;224394999.7;25.14160860514686 +2022-03-08T02:40:00Z;86.61562251781423;3.1116049895671254;9.985425843984602;75769989450.32259;25.14584332387091;223970018.6;25.14584332387091 +2022-03-08T02:50:00Z;87.73179525925363;3.0834012518671448;8.894175949419038;75766498072.7742;25.149292501096852;222227555.1;25.149292501096852 +2022-03-08T03:00:00Z;87.56776727094703;3.0814568809099487;9.093064933424186;75762205530.83871;25.15353315902631;221217626.8;25.15353315902631 +2022-03-08T03:10:00Z;87.66562450931563;3.048521237707641;9.012903917242527;75780692166.19354;25.135269971855443;219741811.6;25.135269971855443 +2022-03-08T03:20:00Z;87.76639836353566;3.021522524092597;8.92427965594756;75777250167.46666;25.138670367102296;218702022.2;25.138670367102296 +2022-03-08T03:30:00Z;87.7272049567671;3.0469200615381866;8.939452896930254;75770976784.51613;25.14486792359763;216951708.9;25.14486792359763 +2022-03-08T03:40:00Z;87.78777742654043;3.0421073391376505;8.880168925108817;75766890826.32259;25.14890449476533;215627473.8;25.14890449476533 +2022-03-08T03:50:00Z;87.93018484212288;3.030011790293996;8.761035354624486;75762954306.06451;25.15279343425568;213416200.3;25.15279343425568 +2022-03-08T04:00:00Z;87.82152282226727;3.0669187077488504;8.833541570758726;75798561957.16129;25.117616173266157;211372098.1;25.117616173266157 +2022-03-08T04:10:00Z;88.00948765812747;3.0357909101005536;8.68679221538912;75813250675.6129;25.103104997531208;209212052.6;25.103104997531208 +2022-03-08T04:20:00Z;87.92102560689287;3.04140619693978;8.74408165257033;75809546768.51613;25.10676413545834;208753631;25.10676413545834 +2022-03-08T04:30:00Z;87.69081330222498;3.0612251992394612;8.956073140861049;75805261689.70493;25.110997420470394;208110360.8;25.110997420470394 +2022-03-08T04:40:00Z;86.47089899166984;3.0869933152289626;10.177809011379887;75801776722.58064;25.1144402647551;205758397.9;25.1144402647551 +2022-03-08T04:50:00Z;87.83871773390743;3.0923578593785894;8.796844591751436;75797465418.32259;25.11869945822673;204373546;25.11869945822673 +2022-03-08T05:00:00Z;87.86766123522621;3.0488493164060007;8.81977381934913;75793896547.09677;25.12222519246309;202877126.2;25.12222519246309 +2022-03-08T05:10:00Z;87.56952536365719;3.2101096755668173;8.896009600881468;75802919506.58064;25.113311293599065;205275730.6;25.113311293599065 +2022-03-08T05:20:00Z;87.98525150623395;3.029613853201058;8.698562240335685;75797929455.48387;25.118241029888182;219324614.2;25.118241029888182 +2022-03-08T05:30:00Z;87.82707195268519;2.999842057705781;8.890029204653986;75791406063.21312;25.12468557383808;219223733.7;25.12468557383808 +2022-03-08T05:40:00Z;87.91078867824963;3.067532880799465;8.75291704381365;75787325037.11476;25.128717272524884;217006608.5;25.128717272524884 +2022-03-08T05:50:00Z;87.81989759722286;3.0798018032737433;8.82287752932108;75783459212.3871;25.132536370982535;215571875.7;25.132536370982535 +2022-03-08T06:00:00Z;87.67445178236366;3.083417552784582;8.957423574494474;75779404766.96774;25.136541810271314;213164164.1;25.136541810271314 +2022-03-08T06:10:00Z;87.84482778857155;3.155026972764319;8.728078723142474;75775696367.48387;25.140205386286006;210489740.4;25.140205386286006 +2022-03-08T06:20:00Z;87.95272333554826;2.9985999437722755;8.770292487567685;75771484730.7541;25.144366116911954;210957741.4;25.144366116911954 +2022-03-08T06:30:00Z;87.87897941241998;3.119233018109844;8.725356450259564;75767865881.18033;25.14794122540738;212404488.3;25.14794122540738 +2022-03-08T06:40:00Z;87.09194319096525;3.0593391234386806;9.546261490195448;75763560381.93549;25.152194684031052;211361329.5;25.152194684031052 +2022-03-08T06:50:00Z;87.7360106427839;3.096819488406678;8.888086939884738;75760027515.87097;25.15568484830092;210183597.4;25.15568484830092 +2022-03-08T07:00:00Z;87.53691222048869;3.0436884682375025;9.14248308236411;75755810144.5246;25.159851244229095;209696221.9;25.159851244229095 +2022-03-08T07:10:00Z;87.60919620202809;3.0887419072949394;9.026638034142186;75774114981.16129;25.14176765837309;207919368.3;25.14176765837309 +2022-03-08T07:20:00Z;87.8831490127238;3.1049065771215285;8.73325780043009;75770768086.70967;25.1450740988712;238694532.1;25.1450740988712 +2022-03-08T07:30:00Z;87.83213765319373;3.1357503155399757;8.750624767862634;75809295393.03226;25.107012472563714;243386500.1;25.107012472563714 +2022-03-08T07:40:00Z;87.86458461025019;3.0210016599920166;8.846523008212996;75816063043.14754;25.1003266231168;246407498.3;25.1003266231168 +2022-03-08T07:50:00Z;87.38066271857859;3.0245480194411165;9.330855686094043;75812102144;25.104239646828685;284595497.3;25.104239646828685 +2022-03-08T08:00:00Z;88.00855226124771;3.006385838867342;8.70025609777116;75808310833.54839;25.107985131665252;285981266.6;25.107985131665252 +2022-03-08T08:10:00Z;87.90308551693859;3.0247513233921106;8.788387352375965;75804159867.87097;25.11208592457059;287049493;25.11208592457059 +2022-03-08T08:20:00Z;87.86484130659802;3.06630732043133;8.800073343651604;75800552084.64516;25.115650100477133;285062177;25.115650100477133 +2022-03-08T08:30:00Z;87.63766982522687;3.1095425619827255;8.968389293945561;75796217195.35484;25.119932593908448;283174515.6;25.119932593908448 +2022-03-08T08:40:00Z;87.88268578246893;3.0284629836326653;8.827698646254296;75792726016;25.123381575336396;281435895.7;25.123381575336396 +2022-03-08T08:50:00Z;87.85332969593046;3.0959452413143067;8.792556890337892;75783826531.09677;25.132173492058534;280376287;25.132173492058534 +2022-03-08T09:00:00Z;87.90020790932395;3.0269876614931803;8.761297454570018;75776406296.7742;25.139504037919565;278355373.4;25.139504037919565 +2022-03-08T09:10:00Z;87.93303149936844;3.0555332562238284;8.73112277242209;75771847118.45161;25.1440081093989;276702056.9;25.1440081093989 +2022-03-08T09:20:00Z;87.94740272095069;3.074933918880612;8.680145817772049;75768038829.41936;25.147770367595808;274914601.3;25.147770367595808 +2022-03-08T09:30:00Z;87.90549209560432;3.1122855058264665;8.687435160567626;75761638300.90323;25.154093532846744;274053714.6;25.154093532846744 +2022-03-08T09:40:00Z;87.94947377200856;3.021017831234191;8.754097548901626;75757610281.29033;25.158072865738127;272353676.4;25.158072865738127 +2022-03-08T09:50:00Z;87.85547055837745;3.0416488371770067;8.814231571103642;75753784370.36066;25.161852532836342;270273833.3;25.161852532836342 +2022-03-08T10:00:00Z;87.20005858450493;3.0147568308792834;9.492410497845448;75749670119.2258;25.165917054968222;269415589.2;25.165917054968222 +2022-03-08T10:10:00Z;86.95679879139361;3.051577182884395;9.688850601424807;75745749124.12903;25.169790656950084;268685774.5;25.169790656950084 +2022-03-08T10:20:00Z;87.87997585945887;3.0546188011288016;8.79791869192898;75742084459.35484;25.173411026877055;267409844.5;25.173411026877055 +2022-03-08T10:30:00Z;87.57879837558428;3.034128221757937;9.09920899985817;75737998104.7742;25.1774479896407;265492347.9;25.1774479896407 +2022-03-08T10:40:00Z;87.30844679994226;3.0192748567527943;9.393939976678388;75733999153.54839;25.181398605494927;263343203.1;25.181398605494927 +2022-03-08T10:50:00Z;87.82947248589635;3.00209109110134;8.884319463356412;75730247277.11476;25.18510513295297;263653177.8;25.18510513295297 +2022-03-08T11:00:00Z;87.2602642924259;3.2021129170665694;9.270032622384873;75778208404.64516;25.137723712148116;264017259.4;25.137723712148116 +2022-03-08T11:10:00Z;87.18850132979374;3.096031971671311;9.422091431225104;75801386347.35484;25.11482592151086;264595059.6;25.11482592151086 +2022-03-08T11:20:00Z;87.04993806652234;3.169436641759004;9.48660531558379;75798300209.54839;25.117874757132505;263156652.1;25.117874757132505 +2022-03-08T11:30:00Z;86.80287999910182;3.1050049550659886;9.822873572025587;75791653392.51613;25.12444123400732;261400609.6;25.12444123400732 +2022-03-08T11:40:00Z;87.2403968503986;3.0221221272240864;9.440781563555905;75787887450.83871;25.12816165670237;257981340.9;25.12816165670237 +2022-03-08T11:50:00Z;87.10450426214818;3.091869590360851;9.532832316518785;75783900457.29033;25.132100459411756;257855554.1;25.132100459411756 +2022-03-08T12:00:00Z;87.4389562503615;3.018512624625694;9.292567782866714;75779790411.54099;25.13616082698867;254563691.4;25.13616082698867 +2022-03-08T12:10:00Z;86.80221502120749;3.030129766676929;9.892600907376558;75776190662.19354;25.139717066122433;252074380.4;25.139717066122433 +2022-03-08T12:20:00Z;87.53607351569998;3.0543480844198267;9.136560260289395;75772010562.06451;25.14384664133091;252775787.4;25.14384664133091 +2022-03-08T12:30:00Z;87.2171727036591;3.0959541152388814;9.407346321004384;75768204981.67741;25.147606223622084;251355606;25.147606223622084 +2022-03-08T12:40:00Z;87.50665572528513;3.029422248006091;9.169579707773854;75764283920.51613;25.15147989086993;250263353.8;25.15147989086993 +2022-03-08T12:50:00Z;87.41765064760669;3.0369658862883093;9.270745829073476;75760120534.70967;25.15559295378205;247862040.8;25.15559295378205 +2022-03-08T13:00:00Z;87.23711520671007;2.9858916591891362;9.485450175817244;75756571396.19672;25.159099193815095;246039651.1;25.159099193815095 +2022-03-08T13:10:00Z;87.42423397466153;3.0185515113013253;9.258192523009772;75746711719.86885;25.16883969611654;244339480.8;25.16883969611654 +2022-03-08T13:20:00Z;87.49462615803262;2.9734951248935966;9.256066558460923;75731301607.2258;25.18406354654266;242785907.6;25.18406354654266 +2022-03-08T13:30:00Z;87.48598488771259;2.9961173069151847;9.218456205163053;75724992908.3871;25.19029599206259;239566451.6;25.19029599206259 +2022-03-08T13:40:00Z;87.32990986726642;3.056148607950013;9.354114255680011;75720726395.87097;25.19451093519061;237225653.7;25.19451093519061 +2022-03-08T13:50:00Z;87.31404225355564;3.150719225483313;9.255618588202786;75717160497.54839;25.198033732457247;236425612.4;25.198033732457247 +2022-03-08T14:00:00Z;87.39161285035055;3.023282231678882;9.30106088248038;75713016732.90323;25.202127411369286;234742354.6;25.202127411369286 +2022-03-08T14:10:00Z;87.47905189806097;3.0054117620064296;9.226350595997944;75709194105.70493;25.20590383442664;232503296;25.20590383442664 +2022-03-08T14:20:00Z;87.27357349317316;3.0969504987465077;9.339563430567917;75709743037.93549;25.205361537146562;231535979.4;25.205361537146562 +2022-03-08T14:30:00Z;86.84142192760878;3.0929525212461217;9.756540981204923;75756920964.12903;25.158753851114586;228374964.5;25.158753851114586 +2022-03-08T14:40:00Z;87.50689731041707;3.0407505922968734;9.184719700256775;75753139959.74193;25.16248915445616;226743279.2;25.16248915445616 +2022-03-08T14:50:00Z;87.26135507468916;3.0511706870227036;9.397287833431234;75748969571.09677;25.16660913556359;225317722.8;25.16660913556359 +2022-03-08T15:00:00Z;87.31231434920359;3.1021317392257575;9.262553944913098;75745334503.2258;25.17020026632545;223593174.7;25.17020026632545 +2022-03-08T15:10:00Z;87.17584141506657;3.0339769269026418;9.401504029750116;75763340651.35484;25.152411758725524;222173184;25.152411758725524 +2022-03-08T15:20:00Z;87.34201509692954;3.005071310421792;9.375950634677778;75759994675.2;25.155717292026313;269931487;25.155717292026313 +2022-03-08T15:30:00Z;87.28805400787789;3.0904209077565308;9.321734748556286;75753896398.45161;25.16174185883026;267896039.2;25.16174185883026 +2022-03-08T15:40:00Z;87.16660486883438;3.1032696022138624;9.46269322626511;75749644618.32259;25.16594224764172;265698119.3;25.16594224764172 +2022-03-08T15:50:00Z;87.39992404232271;3.071255981482358;9.276508850030375;75745905168.51613;25.169636498673366;265106597.2;25.169636498673366 +2022-03-08T16:00:00Z;86.99892490250694;3.0628289990118582;9.633986121000357;75741855413.67741;25.173637304076603;265939472.5;25.173637304076603 +2022-03-08T16:10:00Z;87.11672123408587;3.06475453769409;9.549317292285618;75737967318.70967;25.177478403593703;264348837.2;25.177478403593703 +2022-03-08T16:20:00Z;87.12229201837071;3.030482457105096;9.556034725762958;75734078629.16129;25.181320090504713;263303366.2;25.181320090504713 +2022-03-08T16:30:00Z;86.91524972421078;3.0000433452815085;9.794510283027753;75721895130.2295;25.19335632733831;262327527.2;25.19335632733831 +2022-03-08T16:40:00Z;86.3655847571323;3.0343611370340553;10.318595452760086;75717914491.87097;25.197288851673125;261690665.3;25.197288851673125 +2022-03-08T16:50:00Z;86.64805083317411;3.1140401886362516;9.936630301175796;75713705653.67741;25.20144681758878;263812750.7;25.20144681758878 +2022-03-08T17:00:00Z;86.75425055384311;3.0469070699399796;9.914041942420054;75710129581.41936;25.20497966581843;263000922.8;25.20497966581843 +2022-03-08T17:10:00Z;86.85097249126385;3.0818400850565753;9.780864410777488;75706638666.32259;25.208428386182426;263294051.1;25.208428386182426 +2022-03-08T17:20:00Z;86.90811116398199;3.032603962236104;9.78158430489198;75703150063.48387;25.211874822236634;264287132.9;25.211874822236634 +2022-03-08T17:30:00Z;86.98659747487193;3.0829624662084263;9.653703334087849;75696409549.63934;25.218533863409228;266065391.5;25.218533863409228 +2022-03-08T17:40:00Z;86.80777323147497;3.0522671883075234;9.867110773369168;75692622294.03279;25.2222753424117;264499001.8;25.2222753424117 +2022-03-08T17:50:00Z;87.05125251748984;3.0694181441005495;9.578765613627375;75701093541.16129;25.21390648734917;261289785.8;25.21390648734917 +2022-03-08T18:00:00Z;86.96119935094703;3.059794333598247;9.677785255246;75740322849.03226;25.175151344594465;259025735.3;25.175151344594465 +2022-03-08T18:10:00Z;87.1946454580224;3.100511565357921;9.426421873774023;75736390094.45161;25.179036563923173;259324696.8;25.179036563923173 +2022-03-08T18:20:00Z;87.11255254795283;3.042603181003231;9.571954421143012;75732390746.83871;25.182987571373356;258552402.6;25.182987571373356 +2022-03-08T18:30:00Z;87.15763045290392;3.0936266239232753;9.486228903528486;75728618595.09677;25.186714129071802;257651480.8;25.186714129071802 +2022-03-08T18:40:00Z;87.18731651561167;3.013750549246883;9.530990590536375;75724484003.67213;25.190798745640148;254698595.1;25.190798745640148 +2022-03-08T18:50:00Z;86.97370900998484;2.997269580701906;9.745607987291526;75720847227.87097;25.194391563688438;253557991.2;25.194391563688438 +2022-03-08T19:00:00Z;86.80288705678264;3.0799372352866174;9.839511544258533;75716517359.48387;25.19866909690424;252972988.9;25.19866909690424 +2022-03-08T19:10:00Z;87.11615073424038;3.0718430200053697;9.452778481700488;75735086443.35484;25.18032445777346;250883105;25.18032445777346 +2022-03-08T19:20:00Z;87.22956017109064;3.0578613812598734;9.425067247922392;75731500659.6129;25.183866900104153;249315195.9;25.183866900104153 +2022-03-08T19:30:00Z;86.95922634303354;3.041817804186149;9.684620317143299;75725391343.48387;25.18990237285562;247815993.8;25.18990237285562 +2022-03-08T19:40:00Z;87.19544789875266;3.020480360303004;9.489579499239396;75721151653.16129;25.194090817990272;246282041.8;25.194090817990272 +2022-03-08T19:50:00Z;87.25799336834449;2.990470131936137;9.421724769297006;75717381529.6;25.197815372022703;244629041.5;25.197815372022703 +2022-03-08T20:00:00Z;87.37574310762959;3.009268665678092;9.31965875577866;75713381871.48387;25.201766686223063;242649946.8;25.201766686223063 +2022-03-08T20:10:00Z;87.2268701551965;3.0223255327758354;9.474519342375366;75709432072.25807;25.205668744178094;241933530.2;25.205668744178094 +2022-03-08T20:20:00Z;87.62511692614052;2.986012021759751;9.097173287058125;75705609315.09677;25.209445295627578;239942358.7;25.209445295627578 +2022-03-08T20:30:00Z;87.41609422779315;3.004494146993926;9.274827941578103;75701494552.7742;25.213510322768453;238932100.1;25.213510322768453 +2022-03-08T20:40:00Z;87.58248881751676;2.982950747660158;9.164542409811366;75697840326.19354;25.217120380668458;242717530.8;25.217120380668458 +2022-03-08T20:50:00Z;87.29485261290017;3.028463929318611;9.388467403041966;75693566480.51613;25.22134256832174;244301757.9;25.22134256832174 +2022-03-08T21:00:00Z;87.11488332277187;3.1599903224583126;9.418920047631733;75690057795.14754;25.224808844168066;243559589.2;25.224808844168066 +2022-03-08T21:10:00Z;86.57749969290808;2.9943024354189283;10.12820079494679;75685351424;25.229458329350905;241938633.4;25.229458329350905 +2022-03-08T21:20:00Z;87.43320297757126;3.0683885286860635;9.230451535241597;75702400363.35484;25.21261546073119;241595845.2;25.21261546073119 +2022-03-08T21:30:00Z;87.31412326399887;3.076120132879807;9.338453179946946;75730809162.32259;25.184550039258404;241043323.9;25.184550039258404 +2022-03-08T21:40:00Z;87.54700863481014;2.982036325466806;9.20163603217535;75726976033.03226;25.188336837468874;240572944.5;25.188336837468874 +2022-03-08T21:50:00Z;87.5111417838535;3.0466152380617295;9.171737311526265;75722962151.2258;25.192302203437638;239439673.8;25.192302203437638 +2022-03-08T22:00:00Z;87.38785293030688;3.0196615475179507;9.315109731172798;75718660230.29507;25.196552126998313;237133824;25.196552126998313 +2022-03-08T22:10:00Z;87.55572542939291;3.019620155599872;9.153813746813436;75706801317.16129;25.208267701306365;234968493.4;25.208267701306365 +2022-03-08T22:20:00Z;87.33788958210172;3.098663246146592;9.287160184683344;75702720247.74193;25.212299442790542;234396194.1;25.212299442790542 +2022-03-08T22:30:00Z;87.52195220098939;3.033206552863367;9.15847172909121;75699010659.09677;25.215964193593102;232556345.8;25.215964193593102 +2022-03-08T22:40:00Z;87.4567903600591;3.0040923132206485;9.260257325204716;75694778962.58064;25.22014474154253;228067856.5;25.22014474154253 +2022-03-08T22:50:00Z;87.37363289232177;3.013791970715274;9.327278723811506;75691237243.87097;25.223643651455546;271001533.9;25.223643651455546 +2022-03-08T23:00:00Z;87.43529984967623;3.0437566802525633;9.23855326024228;75686929903.48387;25.22789892896755;272863033.8;25.22789892896755 +2022-03-08T23:10:00Z;87.20600593068008;3.0352957232548046;9.45941327718296;75730931913.44263;25.18442877183263;271144629.7;25.18442877183263 +2022-03-08T23:20:00Z;87.04999978262087;3.085880130416016;9.590002559608516;75728172329.29033;25.187155000858073;271671956.6;25.187155000858073 +2022-03-08T23:30:00Z;87.27999632497382;2.9655686885134767;9.462388611442528;75722002365.93549;25.19325038779161;273109126.3;25.19325038779161 +2022-03-08T23:40:00Z;87.40419064463453;3.0974418437545252;9.205538210078487;75717853712.51613;25.197348896387158;271516374.7;25.197348896387158 +2022-03-08T23:50:00Z;87.20191909585539;3.106779143513968;9.412434738357987;75713985172.64516;25.201170677170158;270007329;25.201170677170158 +2022-03-09T00:00:00Z;87.17138572196396;3.071709301327425;9.474058946626238;75710079504.51613;25.205029137441525;267996919.7;25.205029137441525 +2022-03-09T00:10:00Z;87.07246099758369;2.9982098021030015;9.670061708816165;75706221468.90323;25.20884054093155;269668219.9;25.20884054093155 +2022-03-09T00:20:00Z;87.40296178862386;2.979414184869638;9.349843226381639;75702516954.2295;25.212500279091834;271145224.3;25.212500279091834 +2022-03-09T00:30:00Z;87.50930884476041;3.035737998893318;9.159730157630339;75698339443.6129;25.21662729608735;270473921;25.21662729608735 +2022-03-09T00:40:00Z;87.28735951488902;3.0460336044758125;9.39499350210841;75694740843.35484;25.22018240002079;269518055.2;25.22018240002079 +2022-03-09T00:50:00Z;87.33313063835385;3.051571546401437;9.348001228579372;75719174870.70967;25.196043707048588;267402471.2;25.196043707048588 +2022-03-09T01:00:00Z;87.75794652209699;3.0388755855128102;8.928490067518442;75742618458.83871;25.172883481851375;266348808.3;25.172883481851375 +2022-03-09T01:10:00Z;87.93022642799278;3.001000817364368;8.794372205465598;75737908719.48387;25.177536294529958;265543283.6;25.177536294529958 +2022-03-09T01:20:00Z;87.89447191214015;3.003831819576396;8.826367530171295;75734271764.98361;25.18112928911741;261596296.5;25.18112928911741 +2022-03-09T01:30:00Z;87.88816843988852;3.0135146721826964;8.819583686537396;75727679890.88524;25.187641487154234;258181648.5;25.187641487154234 +2022-03-09T01:40:00Z;87.16382923470799;3.0087915933520923;9.548655356223037;75723772762.83871;25.191501389697052;255724577;25.191501389697052 +2022-03-09T01:50:00Z;87.68115276915199;3.0203366877615996;9.01809083354675;75719795745.03226;25.195430337241422;256027482.8;25.195430337241422 +2022-03-09T02:00:00Z;87.72837335887081;3.000824514706991;9.009648768829065;75715815093.67741;25.199362874415428;253847023.5;25.199362874415428 +2022-03-09T02:10:00Z;87.56877749186069;3.0881127319608876;9.052480026296019;75712006342.19354;25.203125589474304;252843965.9;25.203125589474304 +2022-03-09T02:20:00Z;87.70594838796458;3.013656818266621;9.002437702464944;75707865550.45161;25.207216331416625;252484442.8;25.207216331416625 +2022-03-09T02:30:00Z;87.74855577221233;2.9902511695885026;8.97876127917293;75727987359.4754;25.187337734940613;250735834.2;25.187337734940613 +2022-03-09T02:40:00Z;87.41693914918845;3.0160132243202016;9.279392485929261;75722218915.67213;25.193036455494234;250032194.1;25.193036455494234 +2022-03-09T02:50:00Z;87.46235058339998;3.0414298715211876;9.225044846629626;75709251517.93549;25.20584711613841;249276151.7;25.20584711613841 +2022-03-09T03:00:00Z;87.71587452020196;2.989895963636499;8.998774494172913;75704937769.29033;25.210108724451786;248176640;25.210108724451786 +2022-03-09T03:10:00Z;87.55431246663198;3.105914022737821;9.05577630621014;75723035548.90323;25.192229692918826;246628814.5;25.192229692918826 +2022-03-09T03:20:00Z;87.5243750675171;3.0154423171674494;9.192640964882836;75719944786.58064;25.195283097160022;244670662.2;25.195283097160022 +2022-03-09T03:30:00Z;87.42536136707739;3.090335165176675;9.221647775739047;75713786054.19354;25.201367388874658;244291013.2;25.201367388874658 +2022-03-09T03:40:00Z;87.39962144947998;3.0538269805928255;9.256480517970344;75709651736.7742;25.20545173474962;244690481.5;25.20545173474962 +2022-03-09T03:50:00Z;87.48238216801256;3.09905305317892;9.151790419750217;75705700754.88524;25.209354961072933;246152026.8;25.209354961072933 +2022-03-09T04:00:00Z;86.53664951541316;3.1589990109667907;9.995762464297092;75701869865.29033;25.213139546659228;245319680;25.213139546659228 +2022-03-09T04:10:00Z;87.50996033728205;3.069634586331876;9.150746877185144;75697832464.51613;25.217128147321684;243686036.6;25.217128147321684 +2022-03-09T04:20:00Z;87.26837485984564;3.0976208924878144;9.340728081417936;75729147111.2258;25.186192001123576;242968972.4;25.186192001123576 +2022-03-09T04:30:00Z;87.31856509156877;3.0655630056843415;9.337572014387584;75745608869.16129;25.169929216654346;243156331.4;25.169929216654346 +2022-03-09T04:40:00Z;86.97462086774928;3.023720411349447;9.717596274035747;75742106062.45161;25.173389684897167;241477836.8;25.173389684897167 +2022-03-09T04:50:00Z;87.74440811132818;2.953301021188987;9.028256175360703;75737852810.4918;25.177591527749357;240580541.9;25.177591527749357 +2022-03-09T05:00:00Z;87.79012469161039;2.9513413150459944;8.980961107089986;75734351343.48387;25.181050672483444;238479360;25.181050672483444 +2022-03-09T05:10:00Z;87.00556117683949;3.022003895617307;9.688531687803254;75731076987.87097;25.184285450920644;237704159;25.184285450920644 +2022-03-09T05:20:00Z;87.282466347621;3.0736107582361707;9.376464100991283;75727446808.7742;25.187871751999;236037813.7;25.187871751999 +2022-03-09T05:30:00Z;87.80970689033049;3.077040102415919;8.851081721387722;75720957093.16129;25.194283026341207;233953610.3;25.194283026341207 +2022-03-09T05:40:00Z;88.00920651898632;2.9896179580613302;8.744181844234035;75716991306.32259;25.19820087866667;232058007.1;25.19820087866667 +2022-03-09T05:50:00Z;87.7585984768855;3.1566243005671732;8.807398299959063;75713085373.93549;25.20205960000201;230084809.4;25.20205960000201 +2022-03-09T06:00:00Z;87.74884463085338;3.088372077057159;8.872571271467649;75709018316.8;25.206077498568952;228776068.1;25.206077498568952 +2022-03-09T06:10:00Z;87.39692449165085;3.09262607784548;9.228474309551709;75705291875.09677;25.209758898726488;229196833;25.209758898726488 +2022-03-09T06:20:00Z;87.60447932146319;3.022258334706151;9.095006454530694;75701086009.80646;25.21391392767242;266376951.7;25.21391392767242 +2022-03-09T06:30:00Z;87.8171861042569;3.0278576457047466;8.889876588248498;75697525198.45161;25.21743169945758;272761096.3;25.21743169945758 +2022-03-09T06:40:00Z;87.91462375607465;3.0627733125314327;8.758589188204832;75693216074.32259;25.221688739151414;270663349.7;25.221688739151414 +2022-03-09T06:50:00Z;87.98969331667776;2.9570456580426923;8.759340251607762;75689617408;25.225243908350855;269247001.2;25.225243908350855 +2022-03-09T07:00:00Z;87.96171509021063;2.975384427315764;8.793971995857449;75685399837.37704;25.229410501146933;267068647.2;25.229410501146933 +2022-03-09T07:10:00Z;87.23068819957795;3.032739956889544;9.461567081664677;75703747947.35484;25.211284164995227;267279855.5;25.211284164995227 +2022-03-09T07:20:00Z;87.68678638668312;2.9916085940365185;9.026448357762968;75700451460.12903;25.214540807540267;271798404.1;25.214540807540267 +2022-03-09T07:30:00Z;87.33043121472285;2.9497113198786047;9.420582315924825;75694136286.96774;25.22077964912756;271395674.8;25.22077964912756 +2022-03-09T07:40:00Z;88.00104594289077;3.0720643616220578;8.66871697657441;75690191244.3871;25.224677007931064;270861411.1;25.224677007931064 +2022-03-09T07:50:00Z;87.82844039774442;3.015904071625095;8.877764550278508;75726211307.01639;25.18909232023218;270005875.6;25.18909232023218 +2022-03-09T08:00:00Z;87.92511819361646;3.094031978114585;8.701011320362232;75740608747.01639;25.174868902262705;268708963.1;25.174868902262705 +2022-03-09T08:10:00Z;87.07239546779967;3.1103218752175286;9.550523522243136;75731942234.83871;25.183430662203417;267540215.7;25.183430662203417 +2022-03-09T08:20:00Z;87.9770911298066;3.0760131256382333;8.676907678401605;75724467166.96774;25.190815378839083;263252826.8;25.190815378839083 +2022-03-09T08:30:00Z;87.92426011408571;3.0443983604292386;8.762937904221022;75720140205.41936;25.195090040351168;261150984.3;25.195090040351168 +2022-03-09T08:40:00Z;88.02052177070942;3.043646928596457;8.67654912595;75716571941.7705;25.198615174354373;259189978.2;25.198615174354373 +2022-03-09T08:50:00Z;88.00180061084673;3.044633745638943;8.682760846549478;75712336004.12903;25.202799912166594;260828311.1;25.202799912166594 +2022-03-09T09:00:00Z;87.93029336397076;3.1101831994126914;8.67903246870207;75708624433.54839;25.20646662094897;258529081.8;25.20646662094897 +2022-03-09T09:10:00Z;87.84681629204464;3.1400931637499867;8.726915384723316;75704040679.2258;25.210994971377904;254669328.5;25.210994971377904 +2022-03-09T09:20:00Z;87.93128345325097;3.0630986884714657;8.727760732286592;75700154434.06451;25.21483424344716;253415490.1;25.21483424344716 +2022-03-09T09:30:00Z;87.56260543195691;3.1365215828531947;8.966580693460452;75693707594.32259;25.221203160159565;251876781.4;25.221203160159565 +2022-03-09T09:40:00Z;87.87459669141124;3.0717837760112876;8.776059702146704;75689515377.31148;25.225344705793226;250998585.8;25.225344705793226 +2022-03-09T09:50:00Z;87.31535261549911;3.1667388291060043;9.21969358599158;75686004934.19354;25.228812718142937;254944843.5;25.228812718142937 +2022-03-09T10:00:00Z;87.30188003760958;3.06519883908877;9.338246858482963;75681697131.35484;25.2330684525169;250785792;25.2330684525169 +2022-03-09T10:10:00Z;87.56907665134622;3.0730883954383965;9.058712385633287;75678098465.03226;25.236623621716344;248191768.8;25.236623621716344 +2022-03-09T10:20:00Z;87.62936105039724;3.2185415397664787;8.852486715191578;75673913211.87097;25.240758287672303;246122363.9;25.240758287672303 +2022-03-09T10:30:00Z;87.74027828460869;3.155298407421276;8.776870481954065;75670148393.29033;25.244477600845467;244925605.2;25.244477600845467 +2022-03-09T10:40:00Z;87.86356551836015;3.0595546709226222;8.766328014611817;75666130641.83606;25.24844678968956;245111246.5;25.24844678968956 +2022-03-09T10:50:00Z;87.9556380087083;3.0319303478632227;8.732116507520619;75662202351.48387;25.252327598748984;243608675.1;25.252327598748984 +2022-03-09T11:00:00Z;87.98020831569893;2.980624560934419;8.754775045048405;75658342003.6129;25.256141286548797;242183251.9;25.256141286548797 +2022-03-09T11:10:00Z;87.93994554162609;3.044889333129906;8.706513481012914;75677577083.87097;25.23713870093726;239758699.4;25.23713870093726 +2022-03-09T11:20:00Z;87.5496829039883;3.0854214428888644;9.091965669958297;75721240774.19354;25.194002774165;238736747.4;25.194002774165 +2022-03-09T11:30:00Z;87.48314269911508;3.03748344137385;9.190406163513021;75723491988.64516;25.19177877016954;237298324.6;25.19177877016954 +2022-03-09T11:40:00Z;87.41503871164365;3.1129476731749213;9.189481589800057;75719878722.06451;25.195348363153553;236274324.6;25.195348363153553 +2022-03-09T11:50:00Z;87.58546007134858;2.9680136503703887;9.158284613261076;75715564407.46666;25.19961053057894;230460383;25.19961053057894 +2022-03-09T12:00:00Z;87.073520988917;3.066410173602347;9.588983583849435;75712002576.51613;25.20312930963592;225542815.5;25.20312930963592 +2022-03-09T12:10:00Z;87.33839449704128;2.9929122626366005;9.403625161756349;75707796182.70967;25.207284860709823;225069022.4;25.207284860709823 +2022-03-09T12:20:00Z;87.44912084306068;3.063656524242359;9.194613203738855;75704072786.58064;25.21096325210505;223290268.9;25.21096325210505 +2022-03-09T12:30:00Z;87.43793085792763;3.0570361537716457;9.232173963712864;75700016293.16129;25.21497071463962;221559907.1;25.21497071463962 +2022-03-09T12:40:00Z;87.20954277095562;3.0613992810755803;9.45007191354767;75696145639.2258;25.218794583934418;219989817.8;25.218794583934418 +2022-03-09T12:50:00Z;87.46029619631489;2.956379047871786;9.308119794737898;75692217412.26666;25.22267533036704;218121975.7;25.22267533036704 +2022-03-09T13:00:00Z;87.0274462883337;3.037785616406467;9.652946985056836;75688197747.6129;25.226646409285777;215873932.4;25.226646409285777 +2022-03-09T13:10:00Z;87.10249319716824;3.034665781799174;9.58304319393115;75684037070.45161;25.230756796292145;216145114.2;25.230756796292145 +2022-03-09T13:20:00Z;87.19618805327599;2.992452883955476;9.559839347161804;75679866880;25.2348765816016;214374796.4;25.2348765816016 +2022-03-09T13:30:00Z;87.26997660855646;3.0786412106959626;9.366027933355289;75673674718.96774;25.240993897908947;213218667.4;25.240993897908947 +2022-03-09T13:40:00Z;87.2976079726219;3.0614720466112955;9.348583821072607;75669665461.67741;25.244954695258155;210883947.4;25.244954695258155 +2022-03-09T13:50:00Z;87.6769969525503;2.9652616542421875;9.082653654174184;75665506105.80646;25.249063776944666;248219581.9;25.249063776944666 +2022-03-09T14:00:00Z;87.17172848756508;2.9118295724189216;9.631080770689247;75661953552.51613;25.25257339048062;261352613.2;25.25257339048062 +2022-03-09T14:10:00Z;87.40659409686613;3.055583142722806;9.250472068021951;75657762287.48387;25.256713995642006;260214381.1;25.256713995642006 +2022-03-09T14:20:00Z;87.2119811611995;3.107210369600539;9.376476204754121;75653901080.7742;25.26052853189971;259171295;25.26052853189971 +2022-03-09T14:30:00Z;87.31225525921913;3.1097479324718855;9.300711178010795;75649839104;25.26454141151176;255022839.7;25.26454141151176 +2022-03-09T14:40:00Z;87.52749711267056;3.0618834594686426;9.113039645029843;75646105137.54839;25.26823024546595;252296225;25.26823024546595 +2022-03-09T14:50:00Z;87.28707466899976;3.0743934061726663;9.352327830671655;75696827358.96774;25.218121104147208;251662996.6;25.218121104147208 +2022-03-09T15:00:00Z;87.31287242503016;3.0793614130975118;9.287690527680606;75693613257.44263;25.221296356788518;250281785.8;25.221296356788518 +2022-03-09T15:10:00Z;87.43223761330695;3.0732933675613356;9.205007696557614;75711892446.96774;25.203238108047127;247587146.3;25.203238108047127 +2022-03-09T15:20:00Z;87.39065062378965;3.010517927310344;9.324694520922;75708709392.51613;25.20638268888129;245402372.2;25.20638268888129 +2022-03-09T15:30:00Z;87.2715407807704;3.101320943600966;9.325717473528014;75695131747.09677;25.219796221137088;244632939.4;25.219796221137088 +2022-03-09T15:40:00Z;87.2621365217678;3.073555384150824;9.324914785185666;75689901419.35484;25.224963329844673;244119618.1;25.224963329844673 +2022-03-09T15:50:00Z;86.86342424736303;2.9975811545820483;9.833712434975793;75685985048.7742;25.22883236320698;242687339.4;25.22883236320698 +2022-03-09T16:00:00Z;86.8006613348808;2.9897151895735306;9.91830347501529;75681976790.03279;25.23279217407675;239719457;25.23279217407675 +2022-03-09T16:10:00Z;86.3583825399422;3.0446183932623874;10.301853642682872;75678128194.06451;25.23659425201925;238586450.6;25.23659425201925 +2022-03-09T16:20:00Z;87.18991671666849;3.100673636410337;9.42822014591645;75673980135.2258;25.240692173220868;235194938.8;25.240692173220868 +2022-03-09T16:30:00Z;87.35982944973918;2.9892648939488606;9.367659943287924;75670332052.64516;25.24429616138346;235182938.8;25.24429616138346 +2022-03-09T16:40:00Z;87.32882284711098;3.0615746160130093;9.320473520751376;75666238695.2258;25.248340042342438;233129521.5;25.248340042342438 +2022-03-09T16:50:00Z;87.36241941825222;3.0821587153225676;9.283265095712258;75662349146.83871;25.252182577711384;231654565.2;25.252182577711384 +2022-03-09T17:00:00Z;87.40084151242107;3.0004229529513577;9.341482505847189;75658466824.39345;25.25601797447854;230421140.6;25.25601797447854 +2022-03-09T17:10:00Z;87.270859214444;3.0421912422497432;9.323980634000753;75675370793.29033;25.239318324057116;229268513;25.239318324057116 +2022-03-09T17:20:00Z;87.1579132651675;3.0915135783846313;9.436913448098007;75672341008.51613;25.242311487786292;229048187.9;25.242311487786292 +2022-03-09T17:30:00Z;87.13605165202438;3.1250086722227803;9.457489488301986;75665613790.96774;25.24895739337521;226580312.1;25.24895739337521 +2022-03-09T17:40:00Z;87.31474490218368;2.981612122972129;9.41406719970335;75661969738.32259;25.2525574003122;225090328.8;25.2525574003122 +2022-03-09T17:50:00Z;87.49075574434623;3.0452676972009955;9.191084556586322;75657686049.03226;25.256789312598535;222702360.8;25.256789312598535 +2022-03-09T18:00:00Z;87.41179062177169;3.114201411804582;9.20119993759972;75654213830.19354;25.260219562686355;220755901.9;25.260219562686355 +2022-03-09T18:10:00Z;87.38317697154713;3.082953991191252;9.249357274925327;75654594761.44263;25.25984323575787;220077419.4;25.25984323575787 +2022-03-09T18:20:00Z;87.174033342401;3.09912507268848;9.457868652642194;75702119853.41936;25.21289258013971;219555972.1;25.21289258013971 +2022-03-09T18:30:00Z;87.01425270224297;3.0078729354763554;9.710281595097337;75698093419.35484;25.21687034664724;217775389.4;25.21687034664724 +2022-03-09T18:40:00Z;87.37604801488155;3.0089921542975335;9.338723179648028;75694289094.19354;25.22062868888453;216478300.3;25.22062868888453 +2022-03-09T18:50:00Z;87.17434025127179;3.069671488709901;9.476217322020652;75690416854.70967;25.22445412456317;215598179.1;25.22445412456317 +2022-03-09T19:00:00Z;87.41114241218386;3.0493729725568146;9.244133202099022;75686432900.12903;25.228389925036865;216193552.5;25.228389925036865 +2022-03-09T19:10:00Z;87.50060923540276;2.9381878698076873;9.278972380571497;75704826186.32259;25.210218958714865;218907086.5;25.210218958714865 +2022-03-09T19:20:00Z;87.41843524860882;2.996180891307173;9.307211614065181;75701409959.86885;25.21359389319834;216762368;25.21359389319834 +2022-03-09T19:30:00Z;87.38758166672874;2.9850120488202503;9.347968315484035;75695417872.51613;25.219513554119125;215211360.5;25.219513554119125 +2022-03-09T19:40:00Z;87.6204393950892;2.999321891324213;9.096843124514178;75691080340.64516;25.223798658190177;225743178.3;25.223798658190177 +2022-03-09T19:50:00Z;87.50506307416036;3.0838562694049507;9.139957007039005;75687651724.3871;25.22718583272228;237029640.3;25.22718583272228 +2022-03-09T20:00:00Z;87.41002480555082;3.0967992031908027;9.201941788863394;75683415139.09677;25.231371210355213;236249286.2;25.231371210355213 +2022-03-09T20:10:00Z;87.45018234673748;3.0324024374426664;9.23142082666553;75679816737.03226;25.234926118490677;234910158.5;25.234926118490677 +2022-03-09T20:20:00Z;87.54769250692569;2.9516232049205895;9.167004562661345;75675738442.32259;25.238955118803126;232745158.2;25.238955118803126 +2022-03-09T20:30:00Z;87.53020565790789;3.063633527717075;9.109102602019433;75671962674.36066;25.24268524901226;230062146.1;25.24268524901226 +2022-03-09T20:40:00Z;86.82717607564105;3.0831625393766258;9.808045283172879;75668065973.67741;25.246534850227462;228551092.5;25.246534850227462 +2022-03-09T20:50:00Z;87.28083969473714;3.1521103883524577;9.26559773840989;75664144119.74193;25.250409300667226;228235364.7;25.250409300667226 +2022-03-09T21:00:00Z;87.51647692214569;3.0263763043459275;9.170638650785117;75660385973.67741;25.254122021975046;228061778.6;25.254122021975046 +2022-03-09T21:10:00Z;87.36113989089381;3.027568703799458;9.327793583247868;75655851569.54839;25.258601618706816;226990011.7;25.258601618706816 +2022-03-09T21:20:00Z;87.60057195556159;2.9974552492658852;9.12805574376479;75652214321.54839;25.26219490324647;256819266.1;25.26219490324647 +2022-03-09T21:30:00Z;87.410234202558;2.960598276396905;9.313336793497209;75645522457.18033;25.26880588296939;277411707.9;25.26880588296939 +2022-03-09T21:40:00Z;86.82915623918329;2.9905275401482663;9.870840533755459;75641970083.67213;25.272315318896247;274253691.9;25.272315318896247 +2022-03-09T21:50:00Z;87.34752415734354;3.0450889849743734;9.313100422601021;75692498745.80646;25.22239739730914;271644804.1;25.22239739730914 +2022-03-09T22:00:00Z;87.42660193791707;3.14309867716023;9.161188214369089;75689831721.29033;25.225032185467853;271130359.7;25.225032185467853 +2022-03-09T22:10:00Z;87.62897319054967;2.955020080740557;9.136145629987668;75685723433.29033;25.229090816541362;269588744.3;25.229090816541362 +2022-03-09T22:20:00Z;87.46465930900487;2.9301917043651837;9.336875580647073;75676244135.86885;25.23845553758083;265801795.1;25.23845553758083 +2022-03-09T22:30:00Z;87.52074296024327;2.9850216565837533;9.235821990114902;75669680590.45161;25.24493974934564;264681670.2;25.24493974934564 +2022-03-09T22:40:00Z;86.9284323966249;3.094647169458487;9.692186619760085;75665752394.32259;25.248820465320787;263431795.6;25.248820465320787 +2022-03-09T22:50:00Z;87.17541831892231;2.96194483750725;9.5792629219908;75661999731.6129;25.252527769551147;269697816.8;25.252527769551147 +2022-03-09T23:00:00Z;87.4820718176801;2.9606580587268727;9.263634464158956;75657914500.12903;25.25656362279291;267836052.6;25.25656362279291 +2022-03-09T23:10:00Z;87.25955136069813;3.0793716271979705;9.363163124365858;75683769244.90323;25.231021384629912;266978799.5;25.231021384629912 +2022-03-09T23:20:00Z;87.59575884418476;2.9144986197638367;9.219238619766072;75680428233.44263;25.234322013244785;266389201.8;25.234322013244785 +2022-03-09T23:30:00Z;87.48927631138552;2.9965743293564753;9.235955811240792;75674498345.29033;25.240180226767624;264325846.7;25.240180226767624 +2022-03-09T23:40:00Z;87.4537071228326;2.9838129206940467;9.300756626963492;75670151828.64516;25.24447420701381;262185092.1;25.24447420701381 +2022-03-09T23:50:00Z;87.62502029309437;2.951905595751092;9.17207068434106;75666610043.87097;25.247973182192816;261728784.5;25.247973182192816 +2022-03-10T00:00:00Z;87.69415330337634;2.8883562114929693;9.14227045128524;75662481209.80646;25.252052110990316;269188063;25.252052110990316 +2022-03-10T00:10:00Z;87.49366106359672;3.022989290135198;9.194547558765048;75658992210.58064;25.255498938640496;269771412.6;25.255498938640496 +2022-03-10T00:20:00Z;87.50012429274595;2.9641232980995103;9.253516021807467;75655083107.09677;25.25936079274352;267701657.6;25.25936079274352 +2022-03-10T00:30:00Z;87.4930828069232;2.9271728191277773;9.31659322194825;75651223278.93333;25.263173967117506;267486439.2;25.263173967117506 +2022-03-10T00:40:00Z;86.92205223548834;3.0690537159083506;9.719489573903816;75647413016.7742;25.266938174592077;265395893.7;25.266938174592077 +2022-03-10T00:50:00Z;87.66130350579702;2.967571212699487;9.10517943189521;75643380967.2258;25.270921488709067;266738721;25.270921488709067 +2022-03-10T01:00:00Z;87.54338247595958;3.06480793900624;9.128804700584068;75639719671.74193;25.27453853007037;264251259.9;25.27453853007037 +2022-03-10T01:10:00Z;87.21537591969184;3.167179824905484;9.282618384442054;75635109821.93549;25.279092660566747;262623760.5;25.279092660566747 +2022-03-10T01:20:00Z;87.34913239939873;3.0761443260477592;9.28970196278235;75681061524.64516;25.233696376640633;260162725.2;25.233696376640633 +2022-03-10T01:30:00Z;87.50481647301834;2.995438075428287;9.203294764695798;75680600735.4754;25.234151596246136;259481868.6;25.234151596246136 +2022-03-10T01:40:00Z;87.23477965295884;2.991663107328718;9.504457238817174;75677017121.03226;25.237691895498397;259254668.4;25.237691895498397 +2022-03-10T01:50:00Z;86.97808923728593;3.010025147348098;9.750105336743927;75672834708.64516;25.241823755016636;257315542.7;25.241823755016636 +2022-03-10T02:00:00Z;87.5143414566292;3.033164053005481;9.162537156435816;75669162512.51613;25.245451565266883;256077031.2;25.245451565266883 +2022-03-10T02:10:00Z;87.42120564230163;3.001683506782856;9.3290174422026;75665141297.54839;25.24942417576093;253879725.4;25.24942417576093 +2022-03-10T02:20:00Z;87.36804937092019;3.0432156125139787;9.327439571955532;75661296276.64516;25.25322272185023;253574111;25.25322272185023 +2022-03-10T02:30:00Z;87.47384950138655;2.933710083790351;9.33096107963277;75657458738.36066;25.257013875763313;252242557.9;25.257013875763313 +2022-03-10T02:40:00Z;87.43329547693915;2.994667117858875;9.327962530466921;75653450454.70967;25.260973711241576;250473240.8;25.260973711241576 +2022-03-10T02:50:00Z;86.79383860586026;2.9826853265540696;9.95941070112086;75649738355.6129;25.264640942151896;221889238.7;25.264640942151896 +2022-03-10T03:00:00Z;87.46707281631751;2.9179808133657326;9.357458892705585;75645606746.83871;25.268722612121124;218201319.2;25.268722612121124 +2022-03-10T03:10:00Z;87.66963672174202;2.988352457875785;9.077334456817931;75663868498.58064;25.250681590392222;217934550.7;25.250681590392222 +2022-03-10T03:20:00Z;87.76505498131286;2.9718989332423686;8.972959361272865;75660180645.16129;25.254324868682936;218461349.2;25.254324868682936 +2022-03-10T03:30:00Z;87.78551457199421;2.98252420639992;8.978474861232668;75646035835.87097;25.268298709493163;218552386.1;25.268298709493163 +2022-03-10T03:40:00Z;87.8210798091502;3.013222554548238;8.904678065624438;75641726771.2;25.2725556904476;218101691.7;25.2725556904476 +2022-03-10T03:50:00Z;87.77203616568193;3.041641114576037;8.937327679425493;75638100562.58064;25.276138069039742;215798288.5;25.276138069039742 +2022-03-10T04:00:00Z;87.77244150818393;2.9544895223472305;9.031558199032181;75634031979.35484;25.280157475251155;215004919.7;25.280157475251155 +2022-03-10T04:10:00Z;88.0542756605485;2.9212111034214927;8.77476397677218;75630262404.12903;25.283881487575837;218582973.9;25.283881487575837 +2022-03-10T04:20:00Z;88.06586797813696;2.9979613168432886;8.685313172420951;75626343919.48387;25.28775260944994;221979416.8;25.28775260944994 +2022-03-10T04:30:00Z;88.11388525877454;2.965963569734193;8.666251513969947;75622396894.96774;25.291651926233243;220599857.5;25.291651926233243 +2022-03-10T04:40:00Z;87.98515864117581;2.947159295602644;8.783766469422842;75618648724.64516;25.295354792376045;219349784.8;25.295354792376045 +2022-03-10T04:50:00Z;87.7983243453358;3.092597218710142;8.841038150283286;75658459505.31148;25.256025205094662;221242687;25.256025205094662 +2022-03-10T05:00:00Z;86.8847902302245;3.0482657148625627;9.804471897932402;75666784652.3871;25.247800684171928;222272346.8;25.247800684171928 +2022-03-10T05:10:00Z;88.0053246170368;2.9823888237651035;8.752921312637122;75663442118.19354;25.25110281711446;224449436.9;25.25110281711446 +2022-03-10T05:20:00Z;87.56554983781479;3.013723379748331;9.15724187688671;75660054726.19354;25.25444926566659;224100352;25.25444926566659 +2022-03-10T05:30:00Z;87.8340608596284;3.053675499001703;8.854754801041352;75653376990.96774;25.261046287026375;222748539.9;25.261046287026375 +2022-03-10T05:40:00Z;87.75335358381045;3.0293119632251995;8.970980769399933;75649722301.93549;25.264656801788327;221494172.9;25.264656801788327 +2022-03-10T05:50:00Z;87.81357050928656;3.0191747242465516;8.921294808078796;75645637010.88524;25.268692713876487;217506396.3;25.268692713876487 +2022-03-10T06:00:00Z;87.12911631306794;3.0584798207352586;9.548319810614275;75641866636.3871;25.272417515812705;214215382.7;25.272417515812705 +2022-03-10T06:10:00Z;87.81916049979505;3.002480643307504;8.933066862046834;75637936854.70967;25.27629979817171;255653227.4;25.27629979817171 +2022-03-10T06:20:00Z;87.75368420897155;3.0100130843790645;8.98816993452021;75634031516.90323;25.280157932113095;259379794.6;25.280157932113095 +2022-03-10T06:30:00Z;87.73025338807238;3.0474726935404424;8.955233738917235;75630249653.67741;25.28389408391259;261426010.8;25.28389408391259 +2022-03-10T06:40:00Z;87.44134523479065;2.9514088706944563;9.365770110521874;75624289114.83871;25.28978257764663;261580800;25.28978257764663 +2022-03-10T06:50:00Z;87.81983830363653;2.9475291974578233;8.973706691435094;75614177544.25807;25.299771929551998;259229497.8;25.299771929551998 +2022-03-10T07:00:00Z;87.92581222372212;2.9637122826238094;8.818637579019988;75609986457.6;25.3039123584952;256861661.9;25.3039123584952 +2022-03-10T07:10:00Z;87.4163309221209;3.0064437384672646;9.322442130047131;75628284498.58064;25.285835486156067;254950234.8;25.285835486156067 +2022-03-10T07:20:00Z;87.85480027502231;3.0195402729422556;8.863470445127478;75624822982.19354;25.289255163152934;253639316.6;25.289255163152934 +2022-03-10T07:30:00Z;88.01194656285321;2.963649694277745;8.763346990658194;75618750992.51613;25.295253760618067;252585257.3;25.295253760618067 +2022-03-10T07:40:00Z;87.40938282120769;3.050432540039224;9.263218061514555;75614618128.51613;25.29933667064117;250530650.8;25.29933667064117 +2022-03-10T07:50:00Z;87.97849132224233;2.96611809356932;8.77701450706063;75610826223.48387;25.303082742871677;249608456.3;25.303082742871677 +2022-03-10T08:00:00Z;87.64545681831048;2.969637650730503;9.118929125109878;75606952200.25807;25.30690994073213;247072107.4;25.30690994073213 +2022-03-10T08:10:00Z;87.64887424062432;2.9985341697540924;9.101211387401367;75602976700.85246;25.31083738822859;246895062;25.31083738822859 +2022-03-10T08:20:00Z;87.21193468763205;3.0240079236322734;9.510877632025196;75637896357.16129;25.27633980622573;244793608.3;25.27633980622573 +2022-03-10T08:30:00Z;87.43029183089631;2.945969926690443;9.380269002965104;75650815603.6129;25.263576714861433;243724354.1;25.263576714861433 +2022-03-10T08:40:00Z;87.81877529862689;2.9926087418916194;8.93837802268249;75647247591.2258;25.267101600639872;242093089;25.267101600639872 +2022-03-10T08:50:00Z;87.8536143522746;3.074390085482705;8.812903469160208;75642986165.67741;25.27131151828639;239503426.1;25.27131151828639 +2022-03-10T09:00:00Z;88.01172579782967;3.046711865916522;8.682784619091445;75639519364.12903;25.27473641656274;238428622.5;25.27473641656274 +2022-03-10T09:10:00Z;87.92122871943583;2.976464810867665;8.847132821571462;75634858689.04918;25.279340758006832;236655532.1;25.279340758006832 +2022-03-10T09:20:00Z;87.21608982605837;3.0221777118449364;9.481023071133945;75631198340.12903;25.28295686424553;235041305.2;25.28295686424553 +2022-03-10T09:30:00Z;86.9400937546063;2.987223000543285;9.796423875699912;75624685105.54839;25.289391373281426;232939916.4;25.289391373281426 +2022-03-10T09:40:00Z;87.88887077105568;2.9664897356475124;8.882603263311678;75620824493.41936;25.293205322145205;230312266.3;25.293205322145205 +2022-03-10T09:50:00Z;88.02898816399583;3.000297276674096;8.72311768265815;75616910501.16129;25.29707200593175;227144472.8;25.29707200593175 +2022-03-10T10:00:00Z;87.88334258615916;2.9953299370718343;8.846209257417609;75612980785.54839;25.300954223024757;224162849;25.300954223024757 +2022-03-10T10:10:00Z;87.70816051389995;3.0081576357376547;9.03598706710959;75609243648;25.304646189746627;225461677.4;25.304646189746627 +2022-03-10T10:20:00Z;87.6893566673882;2.9464401755936533;9.118379493255123;75605175978.66667;25.308664693111783;225482114.1;25.308664693111783 +2022-03-10T10:30:00Z;87.57619534011307;3.0626547959155093;9.078541217538147;75601595811.67213;25.31220158658478;224744745.3;25.31220158658478 +2022-03-10T10:40:00Z;87.90987609666792;3.0706899748628524;8.676801837825478;75597365578.32259;25.316380689052938;223093132.4;25.316380689052938 +2022-03-10T10:50:00Z;87.96472730361442;3.018641687269843;8.764343017320405;75593896596.64516;25.31980774110708;221943279.5;25.31980774110708 +2022-03-10T11:00:00Z;88.02771686002426;3.0227377034194847;8.701012147776522;75589653074.58064;25.323999971669334;216431781.2;25.323999971669334 +2022-03-10T11:10:00Z;87.4894449219876;3.181382473406324;9.06138700149455;75628141072.51613;25.285977178628006;215145703.2;25.285977178628006 +2022-03-10T11:20:00Z;87.44197218975383;3.069121535069347;9.217760157353048;75626144668.90323;25.287949451686423;212840051.6;25.287949451686423 +2022-03-10T11:30:00Z;87.26687303197052;3.036481305753785;9.430739582376367;75614326519.74193;25.29962475473659;211483127.6;25.29962475473659 +2022-03-10T11:40:00Z;87.56614620166152;2.956230742811135;9.243151205034918;75599136173.41936;25.314631495160402;209629844.6;25.314631495160402 +2022-03-10T11:50:00Z;87.34353503119506;3.12296495118409;9.272062588530938;75628971767.74193;25.285156524025396;207177331.6;25.285156524025396 +2022-03-10T12:00:00Z;88.0335039625564;2.9735509220777643;8.762935606955121;75649520012.3871;25.2648566462605;205607770.8;25.2648566462605 +2022-03-10T12:10:00Z;87.7437723882495;3.031776548244384;8.95791917059054;75645482743.74193;25.268845116390963;203356490.3;25.268845116390963 +2022-03-10T12:20:00Z;87.65003734101937;2.974519595161408;9.098183785796158;75641842588.90323;25.272441272634342;203211478.7;25.272441272634342 +2022-03-10T12:30:00Z;87.65879266946347;2.973300038607966;9.116018102766096;75637616438.55737;25.27661634145012;208003336.3;25.27661634145012 +2022-03-10T12:40:00Z;87.67718835609881;3.0137860992690833;9.053445291347785;75634166750.96774;25.280024332624336;205898063.7;25.280024332624336 +2022-03-10T12:50:00Z;87.61943958777509;2.98818746257522;9.138032516251858;75629889866.32259;25.284249522513345;204174699.4;25.284249522513345 +2022-03-10T13:00:00Z;87.68371947103002;3.0016892899389966;9.075875090393616;75626365588.64516;25.287731202204064;223017554.6;25.287731202204064 +2022-03-10T13:10:00Z;87.21924110087046;2.961625838140368;9.531488124799276;75621798152.25807;25.292243431932597;237365314.1;25.292243431932597 +2022-03-10T13:20:00Z;87.79875214449577;2.909809168108372;9.024902365761323;75618111752.25807;25.295885274371436;235377564.9;25.295885274371436 +2022-03-10T13:30:00Z;87.86037325200189;2.9552024140292463;8.922334472256686;75611700442.2295;25.302219090818532;232262556.9;25.302219090818532 +2022-03-10T13:40:00Z;87.9549116382949;2.9728096400577457;8.79880017775205;75607748406.55737;25.30612335818795;268443715.1;25.30612335818795 +2022-03-10T13:50:00Z;86.95548982017557;3.069433553209999;9.715123669034787;75603925784.7742;25.309899775895634;274452017.5;25.309899775895634 +2022-03-10T14:00:00Z;87.80575181706072;2.9589219188606983;8.991081593506252;75599927956.64516;25.313849282227974;271969095.3;25.313849282227974 +2022-03-10T14:10:00Z;87.5454393267808;2.8579615667901503;9.268329254782607;75596243406.45161;25.317489297218998;270574978.1;25.317489297218998 +2022-03-10T14:20:00Z;87.42883664213795;3.0285739785880255;9.286763676425112;75592096140.3871;25.321586435228685;268718410.3;25.321586435228685 +2022-03-10T14:30:00Z;87.48180955779773;2.992500696502466;9.2755844134236;75588568889.80646;25.325071051889125;266795140.1;25.325071051889125 +2022-03-10T14:40:00Z;87.47040954291897;2.983901444701616;9.296308447024723;75584358333.93549;25.329230714720612;263670090.3;25.329230714720612 +2022-03-10T14:50:00Z;87.54525137583161;2.9501934799116163;9.222308337546767;75580806639.48387;25.332739479798654;262785816.8;25.332739479798654 +2022-03-10T15:00:00Z;87.49208324491218;2.984791600279773;9.275283693270774;75576630305.03226;25.336865334845502;260774086.2;25.336865334845502 +2022-03-10T15:10:00Z;87.12934012642374;3.0590658512115048;9.511631080156768;75587931367.2258;25.325700868726663;259091137;25.325700868726663 +2022-03-10T15:20:00Z;87.35601798864691;3.021982763454978;9.350275640268542;75609942148.12903;25.30395613239706;256724001;25.30395613239706 +2022-03-10T15:30:00Z;87.50836755513426;2.9798868752161574;9.275994009771841;75632420665.80646;25.28174931283328;255833583.5;25.28174931283328 +2022-03-10T15:40:00Z;87.60612678761088;2.9201207314210142;9.216601842128783;75628505860.19672;25.285616800140506;254427069.9;25.285616800140506 +2022-03-10T15:50:00Z;87.2569656514635;3.0463981444654076;9.441097488314698;75624500323.09677;25.289573922265323;252709062.2;25.289573922265323 +2022-03-10T16:00:00Z;87.01619448968887;2.9512631116457952;9.762345240583542;75620823370.32259;25.293206431667095;251937692.9;25.293206431667095 +2022-03-10T16:10:00Z;87.27786137732107;3.007011405186848;9.435837101356524;75616656417.03226;25.297323018942855;250628532.5;25.297323018942855 +2022-03-10T16:20:00Z;87.21755337569553;3.042213541768506;9.474775203700286;75613149316.12903;25.300787729475257;248822486.7;25.300787729475257 +2022-03-10T16:30:00Z;86.81793935270103;3.1099956688207775;9.81091481907582;75608857302.70967;25.30502786527677;247181245.9;25.30502786527677 +2022-03-10T16:40:00Z;86.84008809660205;2.96928182500446;9.932240533725473;75605353240.7742;25.308489573573475;244977796.1;25.308489573573475 +2022-03-10T16:50:00Z;86.92979834396755;3.0283267523235464;9.789089313952035;75601156505.6;25.312635582759132;242595906.1;25.312635582759132 +2022-03-10T17:00:00Z;86.87703799691792;2.945558395147734;9.92344071979579;75597505569.03226;25.316242390412654;240173056;25.316242390412654 +2022-03-10T17:10:00Z;87.04037133933012;2.956239107118537;9.743372206552854;75594374837.67741;25.31933528057992;238341813.7;25.31933528057992 +2022-03-10T17:20:00Z;87.02258304204902;3.08743731745652;9.606988434392683;75590568926.96774;25.32309518920106;236273731.1;25.32309518920106 +2022-03-10T17:30:00Z;87.26015368772791;2.996221978149526;9.48484280478493;75584333427.6129;25.329255320000172;234322448.5;25.329255320000172 +2022-03-10T17:40:00Z;87.301483825786;3.0825920056291403;9.326068150403044;75580271384.7742;25.33326826487821;232111203.1;25.33326826487821 +2022-03-10T17:50:00Z;87.46368491195116;2.9942000537691773;9.262932936497515;75576575075.09677;25.33691989721608;230232988.9;25.33691989721608 +2022-03-10T18:00:00Z;87.29899466162908;2.994114982628299;9.466609910048033;75572401135.21312;25.34104338663814;227957132.4;25.34104338663814 +2022-03-10T18:10:00Z;86.45770373332694;3.134145758731105;10.144022407008359;75568899369.29033;25.34450282667409;226173456.5;25.34450282667409 +2022-03-10T18:20:00Z;87.10931908405956;2.9981867075215565;9.602562182664238;75564512355.09677;25.3488368149743;225761313.6;25.3488368149743 +2022-03-10T18:30:00Z;87.33635326606023;3.0001062965592995;9.402846307687064;75560934102.70967;25.352371816981734;231379279.7;25.352371816981734 +2022-03-10T18:40:00Z;87.20499672277037;2.9177084804722635;9.60771749273211;75556556205.41936;25.356696798574834;230561990.2;25.356696798574834 +2022-03-10T18:50:00Z;86.92545391830744;3.0610261926422297;9.734528480762421;75572906151.86885;25.340544474124812;230055407.5;25.340544474124812 +2022-03-10T19:00:00Z;87.12130428976323;3.00053425890349;9.616415573486927;75603519588.72131;25.31030106225194;227225401.8;25.31030106225194 +2022-03-10T19:10:00Z;86.95409345745;3.061149750757566;9.71533048496385;75621183752.25807;25.292850405672397;226703161.8;25.292850405672397 +2022-03-10T19:20:00Z;86.72150938855711;3.010271014074953;9.999282121074105;75618308690.58064;25.295690716444735;225015940.1;25.295690716444735 +2022-03-10T19:30:00Z;86.93248013128417;2.999577267378668;9.817357147574764;75611618072.7742;25.30230046467325;223865268.5;25.30230046467325 +2022-03-10T19:40:00Z;86.7563895538797;3.0245347877392095;9.948824433262487;75608100731.87097;25.305775291434657;220813642.3;25.305775291434657 +2022-03-10T19:50:00Z;87.13464404205918;2.968396251830875;9.65005902322204;75603824111.48387;25.31000022025968;220944450.1;25.31000022025968 +2022-03-10T20:00:00Z;86.96985601143766;2.9885294865633667;9.781067176203583;75600291000.65573;25.313490626334715;219932407.7;25.313490626334715 +2022-03-10T20:10:00Z;86.70612220383076;2.9277781193654313;10.083393021821927;75596150519.74193;25.317581061205896;217329201.5;25.317581061205896 +2022-03-10T20:20:00Z;86.98646093121391;3.018022271058837;9.73247692202203;75592430691.09677;25.321255928237466;215583248.5;25.321255928237466 +2022-03-10T20:30:00Z;86.86951646871529;3.000565903141106;9.865058453507842;75588442045.93549;25.325196362596692;211954258.6;25.325196362596692 +2022-03-10T20:40:00Z;87.11607041458164;3.041958501491934;9.567158763103226;75584190397.93549;25.329396620876167;204020282.8;25.329396620876167 +2022-03-10T20:50:00Z;87.2198569994312;2.9962494885097817;9.521852960187077;75580383628.3871;25.333157377955214;202828502.7;25.333157377955214 +2022-03-10T21:00:00Z;87.01761271716279;3.036275032469184;9.671588688826883;75576286571.35484;25.337204913809817;202021326.5;25.337204913809817 +2022-03-10T21:10:00Z;87.10823271970607;2.966799067313864;9.66935616276092;75572290543.21312;25.34115264191132;234530221.4;25.34115264191132 +2022-03-10T21:20:00Z;86.92923492353482;3.0108721388222257;9.797361073251594;75568032999.2258;25.34535872491322;245303956.6;25.34535872491322 +2022-03-10T21:30:00Z;86.92646173466193;2.97814890247958;9.825024281252672;75556379218.58064;25.356871646171495;243931532.4;25.356871646171495 +2022-03-10T21:40:00Z;87.18348245573522;2.985326861609318;9.563021733785318;75549470059.35484;25.36369729430661;241184969.4;25.36369729430661 +2022-03-10T21:50:00Z;87.17878090171979;3.0034173184598556;9.53985598927125;75545896893.93549;25.367227270832547;238859891.6;25.367227270832547 +2022-03-10T22:00:00Z;87.1503941730815;3.0132775145546984;9.54775303194748;75541815428.12903;25.371259403912685;236445497.8;25.371259403912685 +2022-03-10T22:10:00Z;87.13590558912047;2.962218128693773;9.623017192059397;75538067388.85246;25.37496214059342;234490120.3;25.37496214059342 +2022-03-10T22:20:00Z;86.89230240142908;3.1124709922589187;9.733346570914144;75550547296.5246;25.362633077715483;231277006.5;25.362633077715483 +2022-03-10T22:30:00Z;86.2509119327352;2.9623541169558054;10.50961267751489;75585917522.58064;25.32769037200736;230044903.2;25.32769037200736 +2022-03-10T22:40:00Z;87.53455745871753;2.9094624506657136;9.295958038148205;75582139821.41936;25.33142241204926;227972723.6;25.33142241204926 +2022-03-10T22:50:00Z;87.25066653003688;3.0255280408716527;9.486302941934504;75578072757.67741;25.335440317142805;225470805.3;25.335440317142805 +2022-03-10T23:00:00Z;87.02266556787914;2.970599931957852;9.760568467414204;75574453413.16129;25.339015914598214;224252168.3;25.339015914598214 +2022-03-10T23:10:00Z;87.01064104259864;3.003786237558298;9.68506050019031;75599248879.48387;25.314520151375433;228567832.8;25.314520151375433 +2022-03-10T23:20:00Z;86.91999725513284;2.938783214560225;9.869821677862681;75596671681.04918;25.317066199181628;227091621.2;25.317066199181628 +2022-03-10T23:30:00Z;86.98291799212197;2.95864303337419;9.787013868795045;75589967475.6129;25.32368937080615;227327471.5;25.32368937080615 +2022-03-10T23:40:00Z;87.25713660256892;2.984584957125917;9.496268087009321;75586315164.90323;25.327297535992315;227199636.6;25.327297535992315 +2022-03-10T23:50:00Z;87.10862323424186;3.032071365620867;9.603021280480627;75582197693.93549;25.331365239038938;225719196.9;25.331365239038938 +2022-03-11T00:00:00Z;87.15821910006754;3.0383941967077828;9.5436720766655;75578463397.16129;25.33505439932308;221951765;25.33505439932308 +2022-03-11T00:10:00Z;87.10781799119557;2.954289563068938;9.66334409676374;75574725665.03226;25.3387469534389;219464274.6;25.3387469534389 +2022-03-11T00:20:00Z;87.27429968367736;3.0533284061729242;9.387328416321717;75570884475.87097;25.342541714100577;216346029.4;25.342541714100577 +2022-03-11T00:30:00Z;87.2998526260981;3.0221438700991627;9.41509138235533;75567090301.90164;25.346290027843484;214470656;25.346290027843484 +2022-03-11T00:40:00Z;86.99256350993967;3.1035536484554838;9.65815892117226;75563054377.29033;25.350277170185457;210951993.8;25.350277170185457 +2022-03-11T00:50:00Z;87.59037672724293;3.089298482804983;9.069676695141432;75559395394.06451;25.35389192723699;217477318.2;25.35389192723699 +2022-03-11T01:00:00Z;87.25740787753101;2.967584986986501;9.507757982618958;75555209744.51613;25.358026984788932;251149328.8;25.358026984788932 +2022-03-11T01:10:00Z;87.93785127513809;2.951107796663727;8.824099542987298;75551296412.90323;25.361893015915534;249807178.3;25.361893015915534 +2022-03-11T01:20:00Z;87.6958361014141;3.0646795052942575;8.960792028844361;75547015630.45161;25.366122056498153;247633589.7;25.366122056498153 +2022-03-11T01:30:00Z;87.60731467140403;2.9857055725932846;9.146940891660817;75541088826.7541;25.371977222848063;246052731.9;25.371977222848063 +2022-03-11T01:40:00Z;87.52305377052802;3.066413102233851;9.141906704749264;75536815335.2258;25.37619906063283;244245999.5;25.37619906063283 +2022-03-11T01:50:00Z;87.23463731663988;3.100598558804478;9.396198898706691;75543962194.58064;25.369138585453005;242615527.2;25.369138585453005 +2022-03-11T02:00:00Z;87.49708750963534;3.1087557042944183;9.125340820537824;75584962890.32259;25.328633465613834;240072968.3;25.328633465613834 +2022-03-11T02:10:00Z;87.78611883717689;3.0491840179898535;8.869300515675574;75581108752.51613;25.332441018410254;238084027.7;25.332441018410254 +2022-03-11T02:20:00Z;87.65801811052548;3.032654416937814;9.012984543693719;75577256200.25807;25.33624700482282;235788155.9;25.33624700482282 +2022-03-11T02:30:00Z;87.42737543623328;3.061250360892489;9.226295714600196;75573251633.54839;25.34020316828649;232942096.5;25.34020316828649 +2022-03-11T02:40:00Z;87.24666639012834;2.95348262201048;9.536753523005098;75569569187.67213;25.343841104395118;230659963.9;25.343841104395118 +2022-03-11T02:50:00Z;86.32448731021837;3.067464034106567;10.325884949164923;75565415589.16129;25.34794449831079;229260122.8;25.34794449831079 +2022-03-11T03:00:00Z;86.61157633231761;2.9635822543529153;10.170593639228596;75561905713.54839;25.35141195001493;227143151.5;25.35141195001493 +2022-03-11T03:10:00Z;87.0770393229085;2.9938217471648745;9.655863599199996;75579447824.51613;25.334081870753533;224811668.6;25.334081870753533 +2022-03-11T03:20:00Z;87.02400638977419;3.077537152956874;9.61107461833065;75572231795.6129;25.34121067942858;223459361.6;25.34121067942858 +2022-03-11T03:30:00Z;87.14826854106039;3.0919105426526743;9.476246586105347;75561673893.16129;25.351640968386217;221421369.8;25.351640968386217 +2022-03-11T03:40:00Z;86.98920191320255;3.0783464773142337;9.651403508663368;75557956310.70967;25.355313616374;220123069.9;25.355313616374 +2022-03-11T03:50:00Z;87.12408331712413;3.0150361027063926;9.597422514209121;75553890371.14754;25.359330410875728;217487492.1;25.359330410875728 +2022-03-11T04:00:00Z;87.08572569470387;3.0644592054144475;9.547055518999084;75550109762.06451;25.36306532369127;215476488.3;25.36306532369127 +2022-03-11T04:10:00Z;87.1757012321955;3.0090280492738892;9.532640994432914;75546229793.03226;25.366898395491155;214327031.7;25.366898395491155 +2022-03-11T04:20:00Z;87.0750035979112;2.9927028407725964;9.666426365799941;75542262486.70967;25.37081774893448;212627254.6;25.37081774893448 +2022-03-11T04:30:00Z;86.65120711258609;3.069338685175054;10.018986585164358;75538526538.32259;25.374508540868458;209659573.7;25.374508540868458 +2022-03-11T04:40:00Z;86.94870768907869;3.099681675041093;9.65971413345325;75534414154.32259;25.378571218433585;240529143.7;25.378571218433585 +2022-03-11T04:50:00Z;87.14113961111528;3.0059738629399586;9.573634562888591;75530869441.04918;25.382073086714996;256514774.7;25.382073086714996 +2022-03-11T05:00:00Z;87.20019441446337;2.974304628896461;9.535155220950733;75526581130.4918;25.386309564411064;254941844.6;25.386309564411064 +2022-03-11T05:10:00Z;86.16660919428064;3.014636129491112;10.487017527935537;75547636967.2258;25.365508229829015;253135112.3;25.365508229829015 +2022-03-11T05:20:00Z;87.08072725556615;3.052235667218001;9.607280563673447;75549596176.51613;25.363572701524962;250976784.5;25.363572701524962 +2022-03-11T05:30:00Z;87.1417941298065;3.0203716185267124;9.566338240482127;75594030377.29033;25.31967557747019;249428923.7;25.31967557747019 +2022-03-11T05:40:00Z;87.16224083511024;3.0921224934551645;9.497161284932242;75589858403.09677;25.32379712496145;246544978.6;25.32379712496145 +2022-03-11T05:50:00Z;87.15603858389066;3.037578718570136;9.565917850972578;75586111950.45161;25.32749829418842;244159719.2;25.32749829418842 +2022-03-11T06:00:00Z;87.08077189796359;2.9937442707366193;9.652560456640193;75582197625.70493;25.331365306444795;241731187.6;25.331365306444795 +2022-03-11T06:10:00Z;87.07499101096793;3.011181842519501;9.642066310314839;75578277755.87097;25.3352377967649;244636506.8;25.3352377967649 +2022-03-11T06:20:00Z;87.29081609614366;3.02647348720364;9.405805173942694;75574469136.51613;25.339000381291772;243870356.6;25.339000381291772 +2022-03-11T06:30:00Z;86.4930381795378;3.0556337999970173;10.174488413745118;75570347635.6129;25.343072065563977;242160757.5;25.343072065563977 +2022-03-11T06:40:00Z;87.19854482432302;3.0423034265456943;9.50159797593579;75566684093.93549;25.346691325969072;240197698.1;25.346691325969072 +2022-03-11T06:50:00Z;87.21966224178797;3.085846584073337;9.41075956043751;75562401990.19354;25.350921671871546;238160598.7;25.350921671871546 +2022-03-11T07:00:00Z;87.19632936638901;3.027327335354976;9.493690164467056;75558897531.87097;25.354383771764216;236401366.7;25.354383771764216 +2022-03-11T07:10:00Z;87.01094516890554;3.0098324056797874;9.698683130833432;75575036676.19672;25.33843970147012;234802209;25.33843970147012 +2022-03-11T07:20:00Z;86.4586385356263;3.0487497066440556;10.222737932363541;75570939441.54839;25.34248741279395;233508005.2;25.34248741279395 +2022-03-11T07:30:00Z;86.9006285840205;3.0961466772870834;9.73337434961752;75566793298.58064;25.346583441281762;230728552.9;25.346583441281762 +2022-03-11T07:40:00Z;87.00629149144784;3.0758959270543236;9.630692090198114;75562970277.16129;25.350360253795216;237988170.3;25.350360253795216 +2022-03-11T07:50:00Z;87.29453379316008;2.987926876045488;9.447462585941132;75559023649.03226;25.354259178982566;244578304;25.354259178982566 +2022-03-11T08:00:00Z;87.09319607330734;3.0848027638529487;9.528614382156677;75555026613.67741;25.358207902122977;242035325.9;25.358207902122977 +2022-03-11T08:10:00Z;87.15295471580397;3.0490427544025414;9.52594897954893;75551238672.51613;25.361950058393877;239872436.5;25.361950058393877 +2022-03-11T08:20:00Z;87.28597577780856;3.0441869238730637;9.3945331558866;75547070531.14754;25.366067819387585;236237989.2;25.366067819387585 +2022-03-11T08:30:00Z;86.95717325852642;3.039031493061466;9.739510741975016;75543439624.25807;25.36965483946179;239286800.5;25.36965483946179 +2022-03-11T08:40:00Z;87.3184318169992;3.0592899792695745;9.32810881029335;75539263421.93549;25.373780563976666;272193007.5;25.373780563976666 +2022-03-11T08:50:00Z;84.64369764593717;3.266364607247728;11.70452715984775;75470355885.41936;25.441855214269776;270252692.6;25.441855214269776 +2022-03-11T09:00:00Z;86.93268709191872;3.1482908836300814;9.667229716775742;75401917142.70967;25.50946673707283;267119516.9;25.50946673707283 +2022-03-11T09:10:00Z;87.10469417735563;3.019525119529226;9.612849531109527;75394695300.12903;25.516601289155318;266577819.3;25.516601289155318 +2022-03-11T09:20:00Z;86.93859026881759;3.078815301599058;9.723763758167447;75390361326.93333;25.520882877564848;264132938.3;25.520882877564848 +2022-03-11T09:30:00Z;86.53918661940376;3.093909403634959;10.09418991183249;75384182321.54839;25.526987197237357;262045828.1;25.526987197237357 +2022-03-11T09:40:00Z;86.7715667913041;3.0298099743017195;9.918439206536831;75380198895.48387;25.5309224755831;1302400231;25.5309224755831 +2022-03-11T09:50:00Z;87.07141416947013;3.0342638271455185;9.634892882373444;75376234297.80646;25.534839153120682;2766395987;25.534839153120682 +2022-03-11T10:00:00Z;87.06159361575887;3.0730987089084767;9.582810329133842;75372393703.2258;25.538633326388428;2443462590;25.538633326388428 +2022-03-11T10:10:00Z;87.1360057496349;2.9493155377916698;9.657954807330084;75368288123.87097;25.5426892815562;2258381278;25.5426892815562 +2022-03-11T10:20:00Z;86.77596430479618;3.0601278992161958;9.893749397009428;75364609123.09677;25.546323814203763;1686919498;25.546323814203763 +2022-03-11T10:30:00Z;86.71844732328644;3.0682415658477082;9.933114142003872;75360336174.16394;25.550545115951444;2217907960;25.550545115951444 +2022-03-11T10:40:00Z;87.36577351208552;2.8901770412475454;9.46360557668547;75356817077.67741;25.554021677076385;2164488830;25.554021677076385 +2022-03-11T10:50:00Z;86.66337949266945;3.0492272509051563;9.979517049966216;75352483311.48387;25.5583030609858;2155603109;25.5583030609858 +2022-03-11T11:00:00Z;86.94250723511263;3.113983790063754;9.692546313814463;75348902350.45161;25.561840738898972;3110200287;25.561840738898972 +2022-03-11T11:10:00Z;86.82877068809708;3.0762149147263056;9.824594694493182;75367846020.12903;25.54312604158489;3173183554;25.54312604158489 +2022-03-11T11:20:00Z;87.21353703083727;3.075657873789423;9.428831282186737;75364873777.54839;25.546062358633694;3167987712;25.546062358633694 +2022-03-11T11:30:00Z;87.00088074593734;3.0855221378759197;9.611452510634575;75358401922.09836;25.552455988689022;3154777121;25.552455988689022 +2022-03-11T11:40:00Z;86.97523560530954;3.0631471515940483;9.688926864191846;75354396870.19354;25.556412631483276;3130144306;25.556412631483276 +2022-03-11T11:50:00Z;86.81453423123784;3.095340728395059;9.803553315956346;75350519543.74193;25.560243092643415;3127608183;25.560243092643415 +2022-03-11T12:00:00Z;86.78553640101008;3.05843084628171;9.850541065551326;75346433981.93549;25.564279272215146;3122898217;25.564279272215146 +2022-03-11T12:10:00Z;86.8414853704786;3.066861751991692;9.82012374264825;75342706621.93549;25.56796157956997;3132035468;25.56796157956997 +2022-03-11T12:20:00Z;86.70001161751803;3.126300911047808;9.89138604667733;75356713094.29507;25.554124403610324;3145784617;25.554124403610324 +2022-03-11T12:30:00Z;86.91122441984791;3.0870527886832266;9.742955066168017;75390403432.91803;25.520841280515683;3141558470;25.520841280515683 +2022-03-11T12:40:00Z;87.08633354749432;3.044225097297618;9.585684534279974;75386093700.12903;25.52509892151261;3138790301;25.52509892151261 +2022-03-11T12:50:00Z;87.07249488017877;3.076988121080237;9.572910813096323;75382545176.7742;25.52860455382297;3135233982;25.52860455382297 +2022-03-11T13:00:00Z;87.0776620287924;3.0975199601492687;9.542753210108184;75378291877.16129;25.532806443752264;3130812315;25.532806443752264 +2022-03-11T13:10:00Z;86.91643306599994;2.992567719479463;9.785782197794015;75374150028.3871;25.536898229950488;3124148753;25.536898229950488 +2022-03-11T13:20:00Z;86.75753485125583;3.0354700876125924;9.93611818388973;75370047884.3871;25.540950791286605;3122494431;25.540950791286605 +2022-03-11T13:30:00Z;87.27430634500621;3.002323756438825;9.441854217293118;75363748500.64516;25.547174034301456;3119981667;25.547174034301456 +2022-03-11T13:40:00Z;87.30070169131854;2.998713780573411;9.4254324389027;75359742546.58064;25.55113156835099;3117500218;25.55113156835099 +2022-03-11T13:50:00Z;87.07409226565227;3.133961364252776;9.500898667205252;75355718358.70967;25.555107115814735;3108496417;25.555107115814735 +2022-03-11T14:00:00Z;86.62043811797534;3.028963299050952;10.068083586826996;75351946867.6129;25.55883302085324;3064351116;25.55883302085324 +2022-03-11T14:10:00Z;86.96103742665534;3.108020967070202;9.646281679893821;75347822625.57378;25.56290741312923;3063284835;25.56290741312923 +2022-03-11T14:20:00Z;87.68674713566212;3.0064298465386305;9.032220827194752;75344167046.29507;25.566518807377186;3061960175;25.566518807377186 +2022-03-11T14:30:00Z;87.3238021411431;3.1586300780424845;9.21715741684003;75339884411.87097;25.570749677547493;3062924453;25.570749677547493 +2022-03-11T14:40:00Z;87.20096486276171;3.079317164919296;9.458966131792476;75336387352.7742;25.574204467648876;3060849895;25.574204467648876 +2022-03-11T14:50:00Z;87.43407616281766;3.049111985675641;9.262659765165084;75332113441.03226;25.578426720568157;3058557457;25.578426720568157 +2022-03-11T15:00:00Z;86.90344776452834;3.0717252008450613;9.750417595637021;75328437413.16129;25.582058316246023;3055662198;25.582058316246023 +2022-03-11T15:10:00Z;86.86785013403544;3.053727098782965;9.796418151063797;75340901276.90323;25.56974510337511;3053007310;25.56974510337511 +2022-03-11T15:20:00Z;86.9950511671855;3.082632193444702;9.648066835331951;75335005047.46666;25.57557006501552;3050311812;25.57557006501552 +2022-03-11T15:30:00Z;86.49082344475111;3.1606273508274567;10.078061036943538;75328604226.06451;25.58189351961236;3044634558;25.58189351961236 +2022-03-11T15:40:00Z;86.80561530327431;3.01533280068717;9.906943303191541;75324536105.29033;25.585912468961816;3040992950;25.585912468961816 +2022-03-11T15:50:00Z;86.90986878873194;3.1202405252387404;9.686044534985225;75349284467.6129;25.56146324039241;3038276113;25.56146324039241 +2022-03-11T16:00:00Z;87.90826433968112;3.00873975582356;8.822970927710305;75375718730.32259;25.535348488934183;3035193410;25.535348488934183 +2022-03-11T16:10:00Z;87.57573726780862;3.1745024495154555;8.973579455248876;75372070779.87097;25.538952346564788;3032600781;25.538952346564788 +2022-03-11T16:20:00Z;87.83205442468709;3.00169544490649;8.874915452831273;75367785901.41936;25.543185433638993;3028859541;25.543185433638993 +2022-03-11T16:30:00Z;87.75808786324697;3.048906035871962;8.923940969794184;75364297610.4918;25.54663156155213;3027020238;25.54663156155213 +2022-03-11T16:40:00Z;87.6539988369934;3.0261589269764717;9.050913461693439;75359993393.54839;25.550883753373572;3024050374;25.550883753373572 +2022-03-11T16:50:00Z;87.33452599195695;3.063897863043277;9.321776687533488;75356383165.93549;25.55445034412186;3022521047;25.55445034412186 +2022-03-11T17:00:00Z;87.66212821461785;3.100758421333915;8.967295621942608;75352218128.51613;25.558565038683813;3021766127;25.558565038683813 +2022-03-11T17:10:00Z;87.62546932240369;3.0746698901963536;9.002972811394;75349308449.03226;25.561439548836756;3019696987;25.561439548836756 +2022-03-11T17:20:00Z;87.78494030162277;3.0327672715531198;8.93056288992499;75345345569.03226;25.565354529458514;3017671865;25.565354529458514 +2022-03-11T17:30:00Z;87.47539491964021;3.034214177313003;9.227090590576069;75339013808.2623;25.571609758159862;3016600675;25.571609758159862 +2022-03-11T17:40:00Z;87.44806475913306;3.1576990611295974;9.13271630930008;75335043270.19354;25.575532304287197;3014377010;25.575532304287197 +2022-03-11T17:50:00Z;86.77782720645244;3.181571825187893;9.769583612163746;75330962927.48387;25.579563327845445;3011900978;25.579563327845445 +2022-03-11T18:00:00Z;87.75415396038032;3.10894302435114;8.856782686890371;75327255783.2258;25.583225663806257;3009487310;25.583225663806257 +2022-03-11T18:10:00Z;87.54772678878439;3.1604434618786947;9.01592088797675;75323012591.48387;25.587417568038553;3007036449;25.587417568038553 +2022-03-11T18:20:00Z;87.73121477781872;3.1018675103056728;8.875004674586707;75319480386.06451;25.5909070796485;3004728840;25.5909070796485 +2022-03-11T18:30:00Z;87.42755877581322;3.1278540984163463;9.176440289022871;75315169610.32259;25.595165750992184;3000685618;25.595165750992184 +2022-03-11T18:40:00Z;87.80150425450356;2.9849245513021976;8.966928777036362;75311685222.4;25.598608023076007;2995451970;25.598608023076007 +2022-03-11T18:50:00Z;87.49452266988747;3.101019000244791;9.144878744856143;75307513150.95082;25.60272966664739;2991015011;25.60272966664739 +2022-03-11T19:00:00Z;87.06391138554682;3.1901062169379784;9.458751406103735;75303855401.29033;25.60634320504371;2984848219;25.60634320504371 +2022-03-11T19:10:00Z;87.41765491392746;3.1759099491340366;9.10827599072584;75321368906.32259;25.589041385957522;2981113988;25.589041385957522 +2022-03-11T19:20:00Z;87.7235115116279;3.108570249810585;8.873732591548606;75348221423.48387;25.562513435494267;2977981869;25.562513435494267 +2022-03-11T19:30:00Z;87.82566083799334;3.054930146454303;8.866849133017983;75367951242.4918;25.543022091046087;2971765844;25.543022091046087 +2022-03-11T19:40:00Z;87.67689486817011;3.103003089519159;8.955035950232396;75363814618.2295;25.547108715881144;2967156406;25.547108715881144 +2022-03-11T19:50:00Z;86.74989443255703;3.024126021968413;9.967152816372408;75360151485.93549;25.55072757185106;2967763340;25.55072757185106 +2022-03-11T20:00:00Z;87.72267041779904;3.0923511754848625;8.931515830519476;75356004418.06451;25.55482451406277;2991881381;25.55482451406277 +2022-03-11T20:10:00Z;87.81067568647573;3.088933390183755;8.8501787236484;75352473996.3871;25.55831226349088;2990335141;25.55831226349088 +2022-03-11T20:20:00Z;87.71900299206682;3.103161033309381;8.883697277573074;75348197838.45161;25.562536735453953;2988632593;25.562536735453953 +2022-03-11T20:30:00Z;87.67315153946623;3.0501266936352556;9.022093915759392;75344752573.93549;25.565940357016412;2986782984;25.565940357016412 +2022-03-11T20:40:00Z;87.31379268818092;2.9734024616011094;9.451903344303123;75340519323.27869;25.57012244032159;2978344691;25.57012244032159 +2022-03-11T20:50:00Z;87.26476059257142;3.0745661874007024;9.390442292878397;75336901400.7742;25.57369663295323;2978716969;25.57369663295323 +2022-03-11T21:00:00Z;87.28852956026729;3.041894945149362;9.409716823362748;75332837376;25.577711535811087;2979413487;25.577711535811087 +2022-03-11T21:10:00Z;87.11103611400907;3.064385489040942;9.545230292422579;75328615985.54839;25.581881902265522;2978291183;25.581881902265522 +2022-03-11T21:20:00Z;87.08095831240426;2.968870014701092;9.666367231489007;75324687723.35484;25.58576268350667;2975418897;25.58576268350667 +2022-03-11T21:30:00Z;86.99242665346418;3.023818227660267;9.726760778415285;75318277020.90323;25.592095899720604;2968970405;25.592095899720604 +2022-03-11T21:40:00Z;87.17436914807699;3.064136661341629;9.496797141954056;75314450564.12903;25.595876106065727;2964428162;25.595876106065727 +2022-03-11T21:50:00Z;86.95040252355913;3.020489331905822;9.74254795655281;75310327505.83606;25.599949328903506;2961909562;25.599949328903506 +2022-03-11T22:00:00Z;86.02621451139748;2.9773032496675;10.74634986713108;75306773603.09677;25.603460275577625;2959237781;25.603460275577625 +2022-03-11T22:10:00Z;86.68612532773237;3.017988817062923;10.029947290909528;75302519841.03226;25.60766262236887;2956421715;25.60766262236887 +2022-03-11T22:20:00Z;86.79969002231381;3.033505493191347;9.906695076002467;75298010409.29033;25.612117548555084;2955201767;25.612117548555084 +2022-03-11T22:30:00Z;86.93783949615984;3.0361008713827533;9.742254414192981;75286446542.45161;25.623541642796162;2953468631;25.623541642796162 +2022-03-11T22:40:00Z;87.29113133593412;3.069994226230863;9.352099527964176;75282880974.45161;25.627064113732857;2952037277;25.627064113732857 +2022-03-11T22:50:00Z;87.28250278631909;3.041926414023714;9.408353375825085;75302527647.4754;25.6076549102823;2950986433;25.6076549102823 +2022-03-11T23:00:00Z;87.4838192334397;2.9722172664178124;9.290682619077284;75330750530.06451;25.579773158014635;2948862745;25.579773158014635 +2022-03-11T23:10:00Z;87.1522463184429;2.9539464409068072;9.609220048970165;75376751054.45161;25.534328642519316;2943606784;25.534328642519316 +2022-03-11T23:20:00Z;87.19964391902452;2.9022460796088416;9.641312060082706;75374439787.35484;25.536611973302872;2937994339;25.536611973302872 +2022-03-11T23:30:00Z;86.6880149879559;2.924351951527238;10.093701374514806;75368215651.09677;25.542760878351103;2936089963;25.542760878351103 +2022-03-11T23:40:00Z;86.98405835115139;3.145449993454118;9.585737128292488;75364088072.25807;25.54683856709472;2933599265;25.54683856709472 +2022-03-11T23:50:00Z;87.19561637041507;3.0839023055838477;9.442980367891463;75360459280.51613;25.55042349758721;2931170052;25.55042349758721 +2022-03-12T00:00:00Z;87.11641344881627;3.040896823505646;9.554404053190519;75356220902.81967;25.554610645961446;2928296927;25.554610645961446 +2022-03-12T00:10:00Z;86.73993850186162;2.9445866786620787;10.027404878038338;75352970273.03226;25.5578219853475;2926246152;25.5578219853475 +2022-03-12T00:20:00Z;87.0424171814653;3.060411358928528;9.62339638658244;75348760774.19354;25.5619806039231;2923501172;25.5619806039231 +2022-03-12T00:30:00Z;86.99388230586847;3.129363088044342;9.621870061924696;75345226917.16129;25.56547174718289;2921883582;25.56547174718289 +2022-03-12T00:40:00Z;86.58110403562499;3.0169701250079313;10.129594655858636;75341066107.87097;25.569582264721248;2912471172;25.569582264721248 +2022-03-12T00:50:00Z;86.56588454659739;3.082333788698185;10.080740274890502;75337389749.67741;25.573214186729075;2909112824;25.573214186729075 +2022-03-12T01:00:00Z;86.91887650057551;3.0787316905769093;9.733297021292266;75333386911.4754;25.577168642577575;2906221667;25.577168642577575 +2022-03-12T01:10:00Z;87.27309950944091;3.049469790764545;9.408487185691817;75329082619.80328;25.581420908224477;2903674153;25.581420908224477 +2022-03-12T01:20:00Z;87.19506091514532;3.114725900800127;9.43403516217359;75325247223.74193;25.585209945807485;2904694454;25.585209945807485 +2022-03-12T01:30:00Z;87.28456642098885;3.0038457633604594;9.452966883954636;75318857067.35484;25.59152286429743;2902885409;25.59152286429743 +2022-03-12T01:40:00Z;87.13444888609204;3.1326494174882065;9.415945221003367;75314832813.41936;25.595498477027178;2902941762;25.595498477027178 +2022-03-12T01:50:00Z;87.20722531463403;3.084102978948575;9.429492283755417;75302562056.25807;25.607620917399004;2900547452;25.607620917399004 +2022-03-12T02:00:00Z;87.15825017257916;3.0641273640423923;9.49771028950048;75299042204.90323;25.61109822426817;2899607415;25.61109822426817 +2022-03-12T02:10:00Z;87.06485930834471;3.0631431162551914;9.599014670574608;75294782648.65573;25.615306295208043;2893909818;25.615306295208043 +2022-03-12T02:20:00Z;86.97952826648604;3.09334315124316;9.664688798948324;75310178370.06451;25.600096662069188;2890059181;25.600096662069188 +2022-03-12T02:30:00Z;87.02243772313176;3.0234945184680755;9.696214181857489;75342889224.25807;25.567781184363866;2888292682;25.567781184363866 +2022-03-12T02:40:00Z;87.67998974961185;3.117262903386206;8.942812459238105;75339283224.7742;25.571343598088582;2885652546;25.571343598088582 +2022-03-12T02:50:00Z;87.6262937560397;3.0961768391689852;9.02358064258106;75335294051.09677;25.575284554575763;2883812302;25.575284554575763 +2022-03-12T03:00:00Z;87.7633827939775;3.055026584886786;8.923236992310466;75331604281.80646;25.578929725580277;2881086893;25.578929725580277 +2022-03-12T03:10:00Z;87.53562787410114;3.09357018825429;9.102831253123458;75349436217.80646;25.561313324405273;2879225460;25.561313324405273 +2022-03-12T03:20:00Z;87.43363692275726;3.1319111677663107;9.159125764783012;75346198998.03279;25.564511415864587;2876478299;25.564511415864587 +2022-03-12T03:30:00Z;87.60802946533425;3.0686052861641993;9.05161844672573;75340006631.2258;25.57062893545946;2874454148;25.57062893545946 +2022-03-12T03:40:00Z;87.33934332168266;3.1524988750514558;9.232636838944915;75335830362.83871;25.574754725240304;2920048708;25.574754725240304 +2022-03-12T03:50:00Z;87.34963407566606;3.093844476729342;9.2891879966507;75332225882.83871;25.578315637847183;2919329858;25.578315637847183 +2022-03-12T04:00:00Z;86.91417056260262;3.1067524393373582;9.685321945743365;75327969147.87097;25.582520921608143;2917695818;25.582520921608143 +2022-03-12T04:10:00Z;87.32310129868716;3.0731710787412316;9.334574936912896;75324516748.3871;25.58593159189792;2915816283;25.58593159189792 +2022-03-12T04:20:00Z;87.45264306638113;3.1363509160213967;9.143329687857419;75320327721.96721;25.59006998550505;2914476771;25.59006998550505 +2022-03-12T04:30:00Z;87.66188739029954;3.0671333717587546;9.027444342337406;75316607412.45901;25.59374532758746;2912577206;25.59374532758746 +2022-03-12T04:40:00Z;86.8510917186914;3.112414210085052;9.767772619656096;75312622426.83871;25.597682146638626;2910854838;25.597682146638626 +2022-03-12T04:50:00Z;87.52375931851356;3.075190908172028;9.132866122691713;75308785531.87097;25.601472665010725;2908656673;25.601472665010725 +2022-03-12T05:00:00Z;87.37959515210208;3.0883316355380894;9.265531197395196;75304931460.12903;25.605280152541134;2907516598;25.605280152541134 +2022-03-12T05:10:00Z;87.46989796240942;3.139724415814003;9.127674107777057;75301851136;25.608323244755358;2905269567;25.608323244755358 +2022-03-12T05:20:00Z;87.68003833519874;3.0997668170222785;8.938207098261778;75298168832;25.611961040702607;2900260600;25.611961040702607 +2022-03-12T05:30:00Z;87.57703445796467;3.055543042329489;9.073072967851855;75291646254.16394;25.618404780061883;2898187693;25.618404780061883 +2022-03-12T05:40:00Z;87.38702959974404;3.157464563856933;9.161662873000761;75288018415.48387;25.621988769012173;2895958809;25.621988769012173 +2022-03-12T05:50:00Z;87.01820576444709;3.158895913095547;9.550564936823509;75298113403.87097;25.612015798871173;2894023449;25.612015798871173 +2022-03-12T06:00:00Z;87.5160249766516;3.1236263479603315;9.074890488494068;75335919880.25807;25.57466628981908;2891884280;25.57466628981908 +2022-03-12T06:10:00Z;87.76174534318939;3.0122837238590785;8.94426824039749;75331708795.87097;25.578826474778523;2879378333;25.578826474778523 +2022-03-12T06:20:00Z;87.8917578435941;3.0229682842621175;8.790074436953581;75328075974.19354;25.582415386496606;2874583745;25.582415386496606 +2022-03-12T06:30:00Z;87.66709915927866;3.0398148674987815;9.022197167004448;75324010958.45161;25.586431268344363;2873306938;25.586431268344363 +2022-03-12T06:40:00Z;87.35010847685851;3.0607090577364526;9.323327554098075;75320188860.85246;25.590207168203836;2871233305;25.590207168203836 +2022-03-12T06:50:00Z;87.05837276096257;3.079382507022902;9.585616207445174;75316330892.3871;25.594018505357944;2869589487;25.594018505357944 +2022-03-12T07:00:00Z;87.56562593198856;3.103788148507601;9.05783837676163;75312378648.7742;25.59792297815474;2866903586;25.59792297815474 +2022-03-12T07:10:00Z;87.63623268366227;3.080424531427476;9.004520938138354;75330450002.58064;25.5800700530192;2866221122;25.5800700530192 +2022-03-12T07:20:00Z;87.57586275707325;3.084036322112377;9.067209449999426;75327056334.45161;25.583422701840714;2864121724;25.583422701840714 +2022-03-12T07:30:00Z;87.29878580628004;3.1349848676250076;9.295138877228448;75321113236.64516;25.589293965352468;2862836703;25.589293965352468 +2022-03-12T07:40:00Z;87.60971949239375;3.0808743235102694;9.025507116941256;75315419841.04918;25.59491854480737;2861048865;25.59491854480737 +2022-03-12T07:50:00Z;87.61097522738355;3.098205689605488;9.026638623551444;75304934685.37704;25.605276966276737;2858767459;25.605276966276737 +2022-03-12T08:00:00Z;87.50457849060882;3.1143146480318507;9.100026602806954;75300709078.70967;25.60945149798547;2857888718;25.60945149798547 +2022-03-12T08:10:00Z;87.25044356471939;3.1456813571069353;9.338404865695926;75297106316.3871;25.613010713676513;2855929327;25.613010713676513 +2022-03-12T08:20:00Z;87.28545147393388;3.054266865826807;9.391945183571298;75293024520.25807;25.61704317308661;2853912378;25.61704317308661 +2022-03-12T08:30:00Z;87.65163848056235;3.113162294389682;8.968551224851641;75289247942.19354;25.620774103606628;2852061382;25.620774103606628 +2022-03-12T08:40:00Z;87.68168877457732;3.1180527963492857;8.903479296178752;75285291470.45161;25.62468275342701;2852225883;25.62468275342701 +2022-03-12T08:50:00Z;87.30374376348644;3.09048342846823;9.317593137530222;75281396786.36066;25.628530362424502;2851378738;25.628530362424502 +2022-03-12T09:00:00Z;87.48417668865747;3.0937180273497678;9.137643623782932;75277611536.51613;25.632269859908615;2849936703;25.632269859908615 +2022-03-12T09:10:00Z;86.82797810450491;3.0501241993950767;9.84890516220289;75273101113.80646;25.636725765084723;2847409185;25.636725765084723 +2022-03-12T09:20:00Z;87.49905342840398;3.1688166526496295;8.977481119843048;75278481209.80646;25.631410698369805;2846932530;25.631410698369805 +2022-03-12T09:30:00Z;87.83526460549614;3.0492964786157413;8.847926135465933;75318675257.80646;25.591702476311625;2845285145;25.591702476311625 +2022-03-12T09:40:00Z;87.36520560870571;3.019600814214809;9.305154471240805;75315147478.70967;25.59518761510001;2843279096;25.59518761510001 +2022-03-12T09:50:00Z;87.6003014755362;3.085973639239426;9.052142059566384;75310888101.16129;25.599395509500713;2841349748;25.599395509500713 +2022-03-12T10:00:00Z;87.32058137406962;3.0675148636493774;9.345023762461649;75307333632;25.602907015750475;2840244090;25.602907015750475 +2022-03-12T10:10:00Z;87.1054860625815;3.0653864235479396;9.552524448574088;75303205326.45161;25.606985422420035;2838705119;25.606985422420035 +2022-03-12T10:20:00Z;86.91972150063707;3.0900696275839294;9.7191971791052;75299505118.96774;25.610640905451525;2836911335;25.610640905451525 +2022-03-12T10:30:00Z;86.9174670465095;3.132504515878995;9.681072513198137;75295526978.06451;25.614570962517785;2835120921;25.614570962517785 +2022-03-12T10:40:00Z;87.24538484039543;3.0050517822387524;9.479079285940161;75291648462.45161;25.618402598465806;2831966549;25.618402598465806 +2022-03-12T10:50:00Z;87.13977226724421;3.12347965990606;9.442949617703796;75287843957.5082;25.6221611183122;2830866498;25.6221611183122 +2022-03-12T11:00:00Z;86.66204922885073;3.0971243727880577;9.982854282771005;75283789229.41936;25.626166836853834;2828376791;25.626166836853834 +2022-03-12T11:10:00Z;86.99961757683565;3.070591473473194;9.64027058987943;75303220190.96774;25.60697073757149;2826615379;25.60697073757149 +2022-03-12T11:20:00Z;87.09488796742212;3.130587202678532;9.496500715551022;75299756890.83871;25.610392176750185;2814182829;25.610392176750185 +2022-03-12T11:30:00Z;87.07894449349253;3.0474688460386155;9.593655906834908;75293870608.51613;25.616207311507516;2810243997;25.616207311507516 +2022-03-12T11:40:00Z;86.9872003194566;3.0727873998773285;9.672688190828387;75289531094.70967;25.62049437355837;2807920376;25.62049437355837 +2022-03-12T11:50:00Z;87.07464746551103;2.994030617501501;9.63706888927001;75285983232;25.623999353208777;2807724737;25.623999353208777 +2022-03-12T12:00:00Z;86.82914711547704;3.0474767558442464;9.841514549824309;75281835595.54099;25.628096857136008;2806132141;25.628096857136008 +2022-03-12T12:10:00Z;86.81872788401246;3.078220295568983;9.842259846666627;75270293834.32259;25.639499112947693;2803987225;25.639499112947693 +2022-03-12T12:20:00Z;86.95583646308796;3.1045353076294755;9.648081959467;75257396851.6129;25.65224020967217;2801776838;25.65224020967217 +2022-03-12T12:30:00Z;87.13765015680626;3.0556956512749114;9.527139043410857;75253519525.16129;25.656070670832307;2800465458;25.656070670832307 +2022-03-12T12:40:00Z;87.15669744124122;3.022151580485222;9.54107409265449;75249712425.29033;25.65983175424132;2798307697;25.65983175424132 +2022-03-12T12:50:00Z;86.9421841877871;3.1266210186983843;9.652723112137538;75249269396.64516;25.66026942799394;2796937084;25.66026942799394 +2022-03-12T13:00:00Z;87.14228083469592;2.979652238464116;9.600934766728928;75297813420.06557;25.612312156768702;2795736758;25.612312156768702 +2022-03-12T13:10:00Z;87.152303753515;3.026595887392073;9.540872403603307;75293145457.31148;25.61692369780082;2794038371;25.61692369780082 +2022-03-12T13:20:00Z;86.1759747099347;3.115583801249144;10.431278351187068;75289662166.70967;25.620364885827208;2792763656;25.620364885827208 +2022-03-12T13:30:00Z;87.10242135472362;3.0097081533377037;9.620136829066107;75282965537.03226;25.62698057326114;2790620722;25.62698057326114 +2022-03-12T13:40:00Z;86.8790214768668;3.144509488813222;9.608576901988643;75279364228.12903;25.630538353100317;2789447151;25.630538353100317 +2022-03-12T13:50:00Z;87.09808420444178;3.0451031461345814;9.573628780294912;75275205995.35484;25.634646325264942;2787994775;25.634646325264942 +2022-03-12T14:00:00Z;87.13525362078019;3.0913958365346446;9.518561877936277;75271534261.67741;25.63827367865321;2785709419;25.63827367865321 +2022-03-12T14:10:00Z;87.20344434237964;3.0155612571063592;9.522352371523581;75267534914.06451;25.6422246861034;2782497429;25.6422246861034 +2022-03-12T14:20:00Z;87.04708813037084;3.115620457746933;9.565855183106901;75263691544.7742;25.64602160054287;2780016508;25.64602160054287 +2022-03-12T14:30:00Z;87.13711938983404;3.064070971218693;9.518796176939297;75259836283.87097;25.64983026286117;2779033666;25.64983026286117 +2022-03-12T14:40:00Z;86.92816480330698;3.0267322877036724;9.767154168383318;75255856755.6129;25.65376169051329;2777243516;25.65376169051329 +2022-03-12T14:50:00Z;87.07054279795821;3.074684796685937;9.575842640915011;75252163947.35484;25.657409863753518;2775181547;25.657409863753518 +2022-03-12T15:00:00Z;86.64308247430203;3.0205992676846987;10.076743841186454;75248008819.6129;25.661514768416424;2773149730;25.661514768416424 +2022-03-12T15:10:00Z;87.22475383500267;3.0518099449486336;9.445128390528877;75266292967.2258;25.643451621515712;2772421203;25.643451621515712 +2022-03-12T15:20:00Z;87.10805066369652;3.1110760879006043;9.505123085937482;75262769482.32259;25.646932518014527;2770853492;25.646932518014527 +2022-03-12T15:30:00Z;86.90412946204957;3.097367406993304;9.741445958982023;75256905595.87097;25.652725527600044;2762606130;25.652725527600044 +2022-03-12T15:40:00Z;87.13124971179825;3.1462056760099566;9.42873099575215;75252616357.16129;25.65696292222984;2760870813;25.65696292222984 +2022-03-12T15:50:00Z;87.17474060323883;3.081733213521032;9.476391668529935;75240900708.72131;25.668536963486144;2760131881;25.668536963486144 +2022-03-12T16:00:00Z;87.21244791544648;3.010667216856501;9.48679625690147;75236548272.2623;25.67283679199331;2758413940;25.67283679199331 +2022-03-12T16:10:00Z;87.48063845139505;3.102961838698393;9.176519019980521;75232765489.54839;25.676573852167046;2757357370;25.676573852167046 +2022-03-12T16:20:00Z;87.39038629320892;3.0408592172631113;9.30925183832907;75228882944;25.680409469340667;2755601970;25.680409469340667 +2022-03-12T16:30:00Z;86.95741380431902;3.0889173838038;9.691636777304714;75278892131.09677;25.63100474389007;2754141217;25.63100474389007 +2022-03-12T16:40:00Z;87.36146325080011;3.054113362964681;9.322569139876826;75276969389.41936;25.6329042453657;2752997171;25.6329042453657 +2022-03-12T16:50:00Z;87.65025659730637;3.0631604703644117;9.04099332062311;75272855948.3871;25.6369679671867;2750462150;25.6369679671867 +2022-03-12T17:00:00Z;87.53661415050546;3.0659643837105732;9.133834275444379;75269300019.2;25.64048091581492;2749276490;25.64048091581492 +2022-03-12T17:10:00Z;87.22021465195999;3.1121705642004436;9.397633936559764;75287753496.7742;25.622250485646212;2747280549;25.622250485646212 +2022-03-12T17:20:00Z;86.83934091179054;3.0922555342609956;9.784253133187104;75285068899.09677;25.62490263455921;2745436622;25.62490263455921 +2022-03-12T17:30:00Z;87.64711402447219;3.1324062639696733;8.951791283636274;75278429150.96774;25.631462127972704;2743681222;25.631462127972704 +2022-03-12T17:40:00Z;87.50988168218424;3.1647428084111207;9.061350668049409;75274749687.74193;25.635097117482236;2741904703;25.635097117482236 +2022-03-12T17:50:00Z;87.6632740335847;3.0809438061327854;8.997085613884114;75270640673.03226;25.639156466481676;2740462844;25.639156466481676 +2022-03-12T18:00:00Z;87.51198583107646;3.033493625178616;9.195733282309426;75266893295.48387;25.642858549432535;2739052478;25.642858549432535 +2022-03-12T18:10:00Z;87.4531802332805;3.00061285547452;9.283224050165382;75262961294.68852;25.646743024086955;2737267481;25.646743024086955 +2022-03-12T18:20:00Z;87.6278182477826;3.123587485247571;8.97672976330113;75259047803.87097;25.65060921249392;2735135182;25.65060921249392 +2022-03-12T18:30:00Z;87.82501436888467;2.971909328717833;8.958784804650302;75255276643.09677;25.654334791202455;2732166507;25.654334791202455 +2022-03-12T18:40:00Z;87.64113412384437;3.1106554451733417;9.001887854337633;75251211429.16129;25.65835086884818;2730426897;25.65835086884818 +2022-03-12T18:50:00Z;87.26811722719532;3.0988707280072876;9.375318146584844;75247618048;25.661900816768142;2729364295;25.661900816768142 +2022-03-12T19:00:00Z;87.66217383071638;3.0849400496990036;8.99485606506587;75243379282.58064;25.66608834817887;2755410581;25.66608834817887 +2022-03-12T19:10:00Z;87.29609509446915;3.0032558855573668;9.431845953748585;75261674066.58064;25.648014693453216;2771932061;25.648014693453216 +2022-03-12T19:20:00Z;87.5388200216773;3.0855582161316137;9.115476567851388;75258114450.88524;25.651531284030874;2770938913;25.651531284030874 +2022-03-12T19:30:00Z;86.8174817191166;3.0192849789073692;9.911289449077266;75252135011.09677;25.657438450258663;2769785361;25.657438450258663 +2022-03-12T19:40:00Z;87.388405555231;2.9928585564755177;9.34151423416599;75247922275.09677;25.66160026686795;2768412936;25.66160026686795 +2022-03-12T19:50:00Z;87.54570423302886;3.082831288373328;9.127778407575017;75244215262.96774;25.665262472296778;2766786090;25.665262472296778 +2022-03-12T20:00:00Z;87.4430673987019;3.197357874744148;9.082376192724825;75291045095.2258;25.618998672784706;2765376017;25.618998672784706 +2022-03-12T20:10:00Z;87.77922098977622;3.024131308669515;8.94819167778706;75294695424;25.61539246557832;2763605289;25.61539246557832 +2022-03-12T20:20:00Z;87.72843294810694;2.976671231949119;9.034819406894709;75290916091.80328;25.619126116941295;2761824124;25.619126116941295 +2022-03-12T20:30:00Z;87.42129559834672;3.051585903824308;9.268756212759385;75286864268.3871;25.6231289659191;2759358398;25.6231289659191 +2022-03-12T20:40:00Z;87.88604297189536;2.9878471657345123;8.862863372004785;75283218762.32259;25.626730408707946;2759706162;25.626730408707946 +2022-03-12T20:50:00Z;87.66560250948095;3.0740494893788126;8.984710246710378;75279025317.16129;25.63087316764711;2759133083;25.63087316764711 +2022-03-12T21:00:00Z;87.7680869054673;3.0271033804198155;8.943290947089336;75275534996.64516;25.634321300617174;2761004888;25.634321300617174 +2022-03-12T21:10:00Z;87.62893524840464;3.1094957217154207;9.010283094823432;75270838404.12903;25.638961125363046;2758818387;25.638961125363046 +2022-03-12T21:20:00Z;87.41357376476083;2.9356784602431656;9.21801062277303;75267289682.58064;25.64246695347137;2755645572;25.64246695347137 +2022-03-12T21:30:00Z;87.68815697928186;3.0450204722155636;9.009727839925999;75260721698.13333;25.648955550611642;2753300348;25.648955550611642 +2022-03-12T21:40:00Z;87.21262119323252;3.0157546152305628;9.486711075807959;75256952039.2258;25.652679645606593;2751395774;25.652679645606593 +2022-03-12T21:50:00Z;87.18324512946208;3.084010842975639;9.460286590056587;75252936902.19354;25.656646251629233;2749047775;25.656646251629233 +2022-03-12T22:00:00Z;87.75959426770103;3.0565772269507625;8.937077264170195;75249104763.87097;25.660432070849804;2749562343;25.660432070849804 +2022-03-12T22:10:00Z;87.11511697071765;3.0688883787315278;9.554043407455104;75242292455.2258;25.667162039038395;2748455751;25.667162039038395 +2022-03-12T22:20:00Z;87.62931452810147;3.037178049694749;9.062519194146988;75232872844.3871;25.67646779492755;2747281606;25.67646779492755 +2022-03-12T22:30:00Z;87.38358752799441;3.041252738669858;9.309827169376236;75229197543.2258;25.68009867267948;2746246309;25.68009867267948 +2022-03-12T22:40:00Z;87.67957785057537;3.016886828877901;9.027224304378182;75225039046.19354;25.684206905908077;2744285713;25.684206905908077 +2022-03-12T22:50:00Z;87.7333890647082;3.0528378495669437;8.951356856938345;75221517741.41936;25.687685648629095;2742490145;25.687685648629095 +2022-03-12T23:00:00Z;87.79032003345324;3.054731820307718;8.900795813600798;75217264640;25.69188734276042;2740431839;25.69188734276042 +2022-03-12T23:10:00Z;87.59270656532911;3.1116374076079576;9.008296704626241;75261341629.93549;25.648343111932636;2739053954;25.648343111932636 +2022-03-12T23:20:00Z;87.49373152067575;3.03654693363349;9.213396023365998;75258300614.19354;25.651347370880718;2737983356;25.651347370880718 +2022-03-12T23:30:00Z;87.54097325796867;3.0904438733276836;9.108820754182638;75295208229.7705;25.614885858097338;2736498490;25.614885858097338 +2022-03-12T23:40:00Z;87.2256368270081;3.078837757745418;9.402152517878402;75303891934.96774;25.606307112949306;2734304553;25.606307112949306 +2022-03-12T23:50:00Z;87.7363537322303;3.084798303323683;8.901221126809462;75300092696.7742;25.61006042970509;2733078132;25.61006042970509 +2022-03-13T00:00:00Z;87.43714355540995;3.16197833719251;9.141749693350821;75296221184;25.613885147457797;2730662152;25.613885147457797 +2022-03-13T00:10:00Z;87.38825923448161;3.021195057788649;9.332549383363546;75292444077.41936;25.617616600105748;2728699442;25.617616600105748 +2022-03-13T00:20:00Z;87.6546464464204;3.007782645627453;9.074691156400862;75288791964.90323;25.62122456949395;2726445593;25.62122456949395 +2022-03-13T00:30:00Z;87.43803352864843;3.0691318104199006;9.241502106857634;75284700445.37704;25.625266634774384;2725630018;25.625266634774384 +2022-03-13T00:40:00Z;87.7930632143186;2.975765469742511;8.978737446251783;75281116243.93443;25.628807513931047;2724012494;25.628807513931047 +2022-03-13T00:50:00Z;87.7135981315384;3.0567528533932395;8.929464019782584;75276842281.29033;25.633029817137245;2721737299;25.633029817137245 +2022-03-13T01:00:00Z;87.31217090988828;3.0268956421842734;9.389515233135379;75273406860.3871;25.636423714066677;2720127505;25.636423714066677 +2022-03-13T01:10:00Z;87.50557865625841;3.0311934507138467;9.179524765422602;75268750633.29033;25.64102366129051;2717958210;25.64102366129051 +2022-03-13T01:20:00Z;87.19968173821218;3.188118847034886;9.324025478207798;75265111931.87097;25.644618381682015;2717042789;25.644618381682015 +2022-03-13T01:30:00Z;87.68881995137137;3.0912572618732685;8.958429294359624;75258637741.41936;25.65101431851575;2714549149;25.65101431851575 +2022-03-13T01:40:00Z;87.6353007479422;2.9827621449117165;9.119889634897543;75254839396.72131;25.65476675257572;2713543251;25.65476675257572 +2022-03-13T01:50:00Z;87.19399343930868;3.0242550482814665;9.496065709947853;75250883947.35484;25.658674392378096;2711503971;25.658674392378096 +2022-03-13T02:00:00Z;87.032234494102;3.122290100458032;9.588436754620263;75246964868.12903;25.66254610164616;2709904681;25.66254610164616 +2022-03-13T02:10:00Z;87.81841213136407;2.975616580167402;8.917884376148105;75243195425.03226;25.666269983438855;2708767975;25.666269983438855 +2022-03-13T02:20:00Z;87.72679845981219;3.0132321812057663;8.995656434776857;75239099292.90323;25.670316605569568;2706773487;25.670316605569568 +2022-03-13T02:30:00Z;87.24939629407626;3.0540063135820046;9.439253510534533;75235495077.16129;25.67387725711246;2704649031;25.67387725711246 +2022-03-13T02:40:00Z;87.57991466014634;3.063124946603219;9.101847972118112;75231248317.93549;25.678072685708408;2720067122;25.678072685708408 +2022-03-13T02:50:00Z;87.50701514598867;3.0534747824380997;9.177728143048284;75227833685.33333;25.6814460456052;2748396775;25.6814460456052 +2022-03-13T03:00:00Z;87.52882442232095;3.153708956555;9.043881405944283;75261099159.08197;25.64858265203803;2746452232;25.64858265203803 +2022-03-13T03:10:00Z;87.62561264968483;3.056926744505737;9.039901805450622;75297293939.6129;25.612825358254888;2744765143;25.612825358254888 +2022-03-13T03:20:00Z;87.63944812866178;2.9762011370111217;9.116017635809085;75294230924.3871;25.615851350778808;2743359884;25.615851350778808 +2022-03-13T03:30:00Z;87.22747111788935;3.033202085923612;9.476290034307576;75288193486.45161;25.621815814129324;2742817641;25.621815814129324 +2022-03-13T03:40:00Z;87.72006195592533;3.004312209723831;9.010157281110416;75284071258.83871;25.62588821632746;2743036810;25.62588821632746 +2022-03-13T03:50:00Z;87.70691690090007;3.0855202771516868;8.949785910597015;75272364098.06451;25.63745387250852;2741745202;25.63745387250852 +2022-03-13T04:00:00Z;87.52433504512967;3.012912041228237;9.208682314754189;75267990645.5082;25.641774463091156;2741209352;25.641774463091156 +2022-03-13T04:10:00Z;87.1544678397548;3.0862855911696414;9.470054093475229;75263979850.32259;25.645736779747107;2740456217;25.645736779747107 +2022-03-13T04:20:00Z;86.82203454368975;2.980224577850441;9.930508124970922;75260291996.90323;25.64938005803781;2740043512;25.64938005803781 +2022-03-13T04:30:00Z;87.2038451571254;3.0300574462712695;9.498340375806638;75256114539.35484;25.653507022606536;2737959785;25.653507022606536 +2022-03-13T04:40:00Z;87.14985663028627;3.080738545790395;9.516538804713118;75252585108.64516;25.656993793044762;2735977373;25.656993793044762 +2022-03-13T04:50:00Z;87.29752694520346;3.029682049162179;9.416229357980097;75248329364.64516;25.661198097815834;2733384803;25.661198097815834 +2022-03-13T05:00:00Z;87.23984913159627;2.968143926204937;9.527979668648449;75244840827.87097;25.664644468604056;2732761220;25.664644468604056 +2022-03-13T05:10:00Z;86.92901072018846;3.087281522872619;9.675610323411206;75241415193.18033;25.66802869760697;2730980268;25.66802869760697 +2022-03-13T05:20:00Z;87.38700596538861;2.9599932695352695;9.400426804399427;75237823587.09677;25.67157689190457;2728542409;25.67157689190457 +2022-03-13T05:30:00Z;87.28104120081399;2.994759137321932;9.470474191338068;75231305595.87097;25.678016100092012;2726648204;25.678016100092012 +2022-03-13T05:40:00Z;87.11570172348978;2.9748199574993777;9.650723051613758;75227403429.16129;25.68187110126572;2724194106;25.68187110126572 +2022-03-13T05:50:00Z;86.9706627528472;3.089134684979002;9.683750971135199;75223529538.06451;25.68569816859419;2723578120;25.68569816859419 +2022-03-13T06:00:00Z;86.72718368535193;2.982450736662248;10.041991636271613;75219555757.41936;25.68962391810488;2721952273;25.68962391810488 +2022-03-13T06:10:00Z;86.82278064053644;3.008379779553955;9.895410739493808;75215829965.63934;25.69330467619481;2713598791;25.69330467619481 +2022-03-13T06:20:00Z;86.83904614078214;3.0870971720510516;9.814543828203739;75211648419.67213;25.697435679765597;2699551975;25.697435679765597 +2022-03-13T06:30:00Z;86.07067959595157;3.1700633346520646;10.492043355927725;75239669297.54839;25.669753490577403;2697808863;25.669753490577403 +2022-03-13T06:40:00Z;87.18252053037627;3.033654068962092;9.540329646345022;75259694509.41936;25.649970323683274;2696618050;25.649970323683274 +2022-03-13T06:50:00Z;87.08186210524751;3.14323077739302;9.526913039815987;75256160916.64516;25.653461205879093;2694468245;25.653461205879093 +2022-03-13T07:00:00Z;87.25410893857904;3.0594205594481667;9.423555047407739;75252004797.93549;25.657567089531902;2692452088;25.657567089531902 +2022-03-13T07:10:00Z;87.20907799390005;3.0310776497963166;9.490134521934685;75270175909.16129;25.639615612746145;2691108454;25.639615612746145 +2022-03-13T07:20:00Z;87.09909122441667;2.97442711311246;9.654585312970362;75266902183.86885;25.64284976848157;2689962975;25.64284976848157 +2022-03-13T07:30:00Z;87.35377357232315;2.992349070818375;9.4070499148709;75260681645.41936;25.64899511920798;2688576017;25.64899511920798 +2022-03-13T07:40:00Z;87.20606282815965;3.0791295478168355;9.439401265262145;75256765208.7742;25.652864217836296;2686356381;25.652864217836296 +2022-03-13T07:50:00Z;87.09394855175127;3.052661500592576;9.567327483270406;75252754498.06451;25.656826451037364;2684474797;25.656826451037364 +2022-03-13T08:00:00Z;87.06726465044808;3.0409489355153174;9.63537241509417;75249081839.48387;25.660454718149552;2683414066;25.660454718149552 +2022-03-13T08:10:00Z;87.16294278436435;3.1092245689938003;9.474893164064618;75244924861.93549;25.66456145026029;2681434381;25.66456145026029 +2022-03-13T08:20:00Z;87.18619440868054;3.0648979761249215;9.46276846411338;75241400650.32259;25.668043064685026;2680049530;25.668043064685026 +2022-03-13T08:30:00Z;87.14274712795051;3.0220653676644025;9.593960756560461;75237104162.13333;25.672287621169833;2677443419;25.672287621169833 +2022-03-13T08:40:00Z;86.71837660268746;3.1008969912272275;9.910607115788354;75233610652.90323;25.675738904311842;2675593943;25.675738904311842 +2022-03-13T08:50:00Z;86.1537052097157;3.0443867200895345;10.49366915148485;75229422162.58064;25.67987676830149;2673560213;25.67987676830149 +2022-03-13T09:00:00Z;86.58309084581052;3.0920786785702075;10.071591959565545;75225777713.54839;25.68347716683445;2671656762;25.68347716683445 +2022-03-13T09:10:00Z;87.21321018883249;3.0548380316680466;9.472554978194639;75221327541.67741;25.687873549424463;2669762890;25.687873549424463 +2022-03-13T09:20:00Z;87.25576825033946;3.0591040498180653;9.431809205582226;75217504586.32259;25.69165029667193;2667327622;25.69165029667193 +2022-03-13T09:30:00Z;87.12958079662998;3.081057762810666;9.547228811847308;75210829757.93549;25.698244446327998;2665880213;25.698244446327998 +2022-03-13T09:40:00Z;87.15550241619123;2.9960758006284913;9.563295542578535;75198781070.68852;25.710147500947222;2660895116;25.710147500947222 +2022-03-13T09:50:00Z;86.94902827130743;3.0866603648955317;9.69592211798444;75195101778.58064;25.71378232140712;2659602432;25.71378232140712 +2022-03-13T10:00:00Z;86.90582817695591;3.0861563758293156;9.746313671240566;75217074836.64516;25.69207485195982;2657354124;25.69207485195982 +2022-03-13T10:10:00Z;87.12909966999104;2.999693618213508;9.580342670052513;75243220727.74193;25.666244986563342;2658108515;25.666244986563342 +2022-03-13T10:20:00Z;87.09329436004322;3.0570590340193076;9.569564836682398;75238949524.64516;25.67046456357689;2666284082;25.67046456357689 +2022-03-13T10:30:00Z;87.13850545887951;3.032639391230997;9.55204491823042;75235526958.16394;25.673845761455873;2703423752;25.673845761455873 +2022-03-13T10:40:00Z;87.19282611732747;3.0226378828686964;9.516120284487405;75231249458.36066;25.67807155906756;2702149434;25.67807155906756 +2022-03-13T10:50:00Z;86.1775143849068;3.1923122411931875;10.363408671878952;75227673236.64516;25.681604554948148;2700596125;25.681604554948148 +2022-03-13T11:00:00Z;87.15558434256913;3.051893066393233;9.539092404343153;75223598113.03226;25.685630422492913;2699344533;25.685630422492913 +2022-03-13T11:10:00Z;86.97434716574843;3.1135862105232586;9.63034202326719;75264864123.87097;25.64486319442374;2697918266;25.64486319442374 +2022-03-13T11:20:00Z;87.18770762546788;3.111260801586817;9.42759888204247;75262425682.58064;25.647272162244843;2695639846;25.647272162244843 +2022-03-13T11:30:00Z;87.10368110428095;3.0333355922016287;9.589241006872827;75256123920.51613;25.65349775483546;2692993156;25.65349775483546 +2022-03-13T11:40:00Z;87.327548183744;2.880100612113902;9.53587976746094;75252284825.6;25.657290446565153;2692825022;25.657290446565153 +2022-03-13T11:50:00Z;87.15669707977064;2.9170395515198417;9.665271125640341;75248220027.87097;25.66130611303512;2691291202;25.66130611303512 +2022-03-13T12:00:00Z;87.09784058898563;3.0868596079094703;9.527521960442916;75244600551.2258;25.664881841022517;2688935407;25.664881841022517 +2022-03-13T12:10:00Z;87.24723111471982;2.9999068028118487;9.483127083022177;75240354188.3871;25.6690768780225;2687386987;25.6690768780225 +2022-03-13T12:20:00Z;87.58976664389925;3.078668890996414;9.063910902150655;75236914935.74193;25.67247456037956;2685413947;25.67247456037956 +2022-03-13T12:30:00Z;87.4047271376924;3.1525382266905275;9.179479069581465;75232664014.45161;25.6766741007331;2684445993;25.6766741007331 +2022-03-13T12:40:00Z;87.74000214139987;2.986586838142722;9.026107044941034;75229088470.70967;25.680206426834797;2682871147;25.680206426834797 +2022-03-13T12:50:00Z;87.86388924340233;3.0230369894720712;8.85757642174358;75224953302.03279;25.684291613678134;2680955012;25.684291613678134 +2022-03-13T13:00:00Z;87.13937340177237;3.0959273992295078;9.491899769661803;75221224679.2258;25.687975168576383;2678423222;25.687975168576383 +2022-03-13T13:10:00Z;87.6770962808917;3.1016899147955628;8.90847112689032;75216855040;25.692291991920293;2677292792;25.692291991920293 +2022-03-13T13:20:00Z;87.44837260474253;3.01052666465521;9.277223447040292;75212925522.58064;25.696174013215316;2675151971;25.696174013215316 +2022-03-13T13:30:00Z;87.4782970874182;3.1920354570999994;9.065994130243087;75227457073.54839;25.68181810527897;2673429924;25.68181810527897 +2022-03-13T13:40:00Z;87.74215120482523;3.0406151462113526;8.96171651173849;75258419266.06451;25.651230153156344;2671408095;25.651230153156344 +2022-03-13T13:50:00Z;87.85240177810725;3.0174619055363525;8.854904041481676;75254789774.68852;25.6548157748264;2669895284;25.6548157748264 +2022-03-13T14:00:00Z;87.90839531306304;3.058575452789513;8.750276391107844;75250550280.39345;25.659004026302917;2668641445;25.659004026302917 +2022-03-13T14:10:00Z;87.63541385127712;3.1323760640810208;8.954949510928214;75247099309.41936;25.662413285349324;2666761447;25.662413285349324 +2022-03-13T14:20:00Z;87.78476912570957;3.117286586787805;8.80116562564521;75242842904.7742;25.666618242780327;2665240444;25.666618242780327 +2022-03-13T14:30:00Z;87.5455275326634;3.046511575263606;9.146217960683883;75239318957.41936;25.670099596141085;2662637501;25.670099596141085 +2022-03-13T14:40:00Z;87.50118285817668;3.066502963832057;9.15973014282916;75235184375.74193;25.674184203080014;2662570353;25.674184203080014 +2022-03-13T14:50:00Z;87.86500201803541;2.994890928274248;8.887848755197936;75231471946.32259;25.67785176032031;2660838367;25.67785176032031 +2022-03-13T15:00:00Z;87.84548299224669;3.0268831082184975;8.864749551213615;75227486845.90164;25.681788692784515;2659440310;25.681788692784515 +2022-03-13T15:10:00Z;87.73687948527825;3.0234549789410545;8.967414195245961;75245369410.06451;25.664122275389847;2657065819;25.664122275389847 +2022-03-13T15:20:00Z;87.27621632656961;3.0281851155987884;9.429511226276892;75242316766.96774;25.667138021152777;2655993988;25.667138021152777 +2022-03-13T15:30:00Z;87.87179601764062;3.0329723738508103;8.811093097946348;75235852684.3871;25.67352397228949;2654783092;25.67352397228949 +2022-03-13T15:40:00Z;87.79994260627169;3.086983649461134;8.831609789861435;75232145077.67741;25.67718676511225;2653230148;25.67718676511225 +2022-03-13T15:50:00Z;87.74205737361557;3.0164995090948694;8.965597675646203;75227929566.96774;25.681351322893256;2650383327;25.681351322893256 +2022-03-13T16:00:00Z;87.19637039933338;3.0688688928455377;9.448758356063058;75224458999.74193;25.684779941331254;2644896867;25.684779941331254 +2022-03-13T16:10:00Z;87.89041978946878;3.0288301015909407;8.805067166117873;75220200448;25.688987019907035;2644241375;25.688987019907035 +2022-03-13T16:20:00Z;87.86000790309768;3.0292376771204705;8.816380943684656;75214638905.80646;25.694481339673175;2641846536;25.694481339673175 +2022-03-13T16:30:00Z;87.64724461552223;3.101665920645541;8.927319071273613;75204135969.03226;25.704857327324202;2642255674;25.704857327324202 +2022-03-13T16:40:00Z;87.88325344445406;3.048522906217932;8.783023238811191;75200440980.64516;25.7085076543422;2640811327;25.7085076543422 +2022-03-13T16:50:00Z;87.90101147654897;3.0688224352290563;8.768004533680072;75196443350.70967;25.712456964876555;2639620600;25.712456964876555 +2022-03-13T17:00:00Z;87.79341394346837;3.1197845327862903;8.776001367079127;75207871256.7742;25.701167188050146;2636518962;25.701167188050146 +2022-03-13T17:10:00Z;87.72894170357756;3.0140429446105887;8.982412915366767;75245422491.27869;25.664069835768938;2635314605;25.664069835768938 +2022-03-13T17:20:00Z;87.36416308777834;3.144028293564626;9.211722525668282;75241405859.67213;25.66803791830095;2633727405;25.66803791830095 +2022-03-13T17:30:00Z;87.25440013069722;3.089880603481218;9.381716246455019;75235349801.29033;25.674020777032215;2631899665;25.674020777032215 +2022-03-13T17:40:00Z;87.77727702737654;3.07742850510735;8.87990170517266;75231083883.35484;25.6782351327663;2631053312;25.6782351327663 +2022-03-13T17:50:00Z;87.82761607420308;3.09547871789831;8.788542068638549;75227579160.7742;25.68169749372293;2629483619;25.68169749372293 +2022-03-13T18:00:00Z;87.78195144769863;3.0953067565542223;8.837256684887356;75223324672;25.68590055844012;2627515623;25.68590055844012 +2022-03-13T18:10:00Z;87.6838900932025;3.0440884396865795;8.985260203850416;75219839345.31148;25.68934375794303;2672945152;25.68934375794303 +2022-03-13T18:20:00Z;87.79574720725697;3.06267628488695;8.852688769760412;75215607908.72131;25.69352404910821;2670659848;25.69352404910821 +2022-03-13T18:30:00Z;87.64890343392914;3.1585700123228557;8.912278999723126;75211978223.48387;25.697109862296507;2669079123;25.697109862296507 +2022-03-13T18:40:00Z;87.7740766534598;3.0711548261934603;8.870845923052698;75207940888.7742;25.701098397692963;2667416873;25.701098397692963 +2022-03-13T18:50:00Z;87.26868504322162;3.0477480355722997;9.392735743348434;75204140659.6129;25.70485269343866;2665083216;25.70485269343866 +2022-03-13T19:00:00Z;87.94902611793025;2.986509925919449;8.767477209013823;75200263267.09677;25.708683219864795;2664363173;25.708683219864795 +2022-03-13T19:10:00Z;87.6997174909906;3.1191067438032825;8.87841098691511;75218021276.90323;25.691139851336544;2662569125;25.691139851336544 +2022-03-13T19:20:00Z;87.8885776723753;3.049119707975931;8.792659402259945;75215046689.57378;25.694078484793152;2660569550;25.694078484793152 +2022-03-13T19:30:00Z;88.02616287835947;3.0018717259873187;8.71400982432897;75208486185.29033;25.700559692182388;2658425493;25.700559692182388 +2022-03-13T19:40:00Z;87.35888166850333;3.0505062279651445;9.27475375065943;75204850060.3871;25.70415186720016;2656826137;25.70415186720016 +2022-03-13T19:50:00Z;87.75320029067355;3.1218430673486908;8.847499616024216;75200590154.32259;25.708360283728815;2655718484;25.708360283728815 +2022-03-13T20:00:00Z;87.6174429408246;3.0350899880767934;9.066093174310188;75197137292.3871;25.711771410880548;2654283247;25.711771410880548 +2022-03-13T20:10:00Z;87.15258236405407;3.101626820523557;9.422741456476173;75192893968.51613;25.715963445644835;2651975019;25.715963445644835 +2022-03-13T20:20:00Z;88.06698590746416;2.9556355114505495;8.695741100436084;75189299992.7742;25.719513980958713;2650350295;25.719513980958713 +2022-03-13T20:30:00Z;87.63616191335406;3.0927716856197365;9.008170857916511;75195446476.8;25.713441789559287;2648544289;25.713441789559287 +2022-03-13T20:40:00Z;87.97095413222007;3.048805782163553;8.709480341134803;75237294542.45161;25.67209954198075;2650866589;25.67209954198075 +2022-03-13T20:50:00Z;88.0052835921444;3.0281165181139147;8.667701238784957;75233373679.48387;25.675973013430625;2650272074;25.675973013430625 +2022-03-13T21:00:00Z;87.91999393828004;3.0252122613656223;8.777327496819527;75229459621.16129;25.67983976248317;2648780934;25.67983976248317 +2022-03-13T21:10:00Z;87.71216858273314;2.98549872993502;9.020064601016907;75225285136.51613;25.68396379008219;2647385187;25.68396379008219 +2022-03-13T21:20:00Z;87.04786420196838;3.033013078210038;9.624371848090608;75221173743.48387;25.688025488657384;2645156567;25.688025488657384 +2022-03-13T21:30:00Z;87.84564615211465;3.038801514679288;8.828833163858901;75215164382.96774;25.693962213960656;2642645521;25.693962213960656 +2022-03-13T21:40:00Z;87.96767726251505;3.0226361369049872;8.726990964445564;75210819953.31148;25.698254132443395;2640166582;25.698254132443395 +2022-03-13T21:50:00Z;87.51698670676649;2.9391682796080305;9.281777276510505;75207395922.58064;25.701636776873574;2638962754;25.701636776873574 +2022-03-13T22:00:00Z;87.86343034319671;3.05666218727722;8.801687103747243;75203125446.19354;25.705855635961207;2636587679;25.705855635961207 +2022-03-13T22:10:00Z;87.97960676872376;3.0312309561535127;8.718478401303155;75199579961.80646;25.709358266035853;2635402928;25.709358266035853 +2022-03-13T22:20:00Z;87.7864527046535;3.0527063038239866;8.892093981046807;75195448286.96774;25.71344000127106;2633579619;25.71344000127106 +2022-03-13T22:30:00Z;87.85668779406758;3.0741106982742354;8.798997989557721;75191740878.45161;25.717102598295856;2631033691;25.717102598295856 +2022-03-13T22:40:00Z;87.81657176753222;3.004458010679316;8.88882984722075;75187773775.7377;25.721021750591518;2629897844;25.721021750591518 +2022-03-13T22:50:00Z;87.52632106414345;3.034015783939321;9.124400573597514;75183891753.29033;25.724856850986882;2628481817;25.724856850986882 +2022-03-13T23:00:00Z;87.89269213438224;3.0553136706161528;8.789508720428513;75180085842.58064;25.72861675960802;2626358107;25.72861675960802 +2022-03-13T23:10:00Z;87.88492933096428;3.099583975322688;8.725492897879239;75204015467.35484;25.704976372496397;2624228011;25.704976372496397 +2022-03-13T23:20:00Z;87.97614737633062;3.062492876360415;8.692773056207516;75201284029.93549;25.707674794998795;2622487915;25.707674794998795 +2022-03-13T23:30:00Z;87.86823183476157;3.0616966103552463;8.794689118744976;75194646329.80646;25.714232265166505;2620289817;25.714232265166505 +2022-03-13T23:40:00Z;87.76207885609459;3.0333063146557255;8.925568801095201;75191151968.5246;25.717684390061503;2618946659;25.717684390061503 +2022-03-13T23:50:00Z;87.94487820134235;2.999756572873783;8.77790986543926;75186875425.03226;25.721909242921182;2617258248;25.721909242921182 +2022-03-14T00:00:00Z;87.27008001601989;3.0501525043370052;9.361662844840806;75185828500.64516;25.722943513120622;2615873536;25.722943513120622 +2022-03-14T00:10:00Z;87.93762032497327;3.1363530029661395;8.65150397116675;75229095737.80646;25.68019924757551;2613744153;25.68019924757551 +2022-03-14T00:20:00Z;87.59254511586234;3.0001254513424542;9.110461458556504;75225257257.29033;25.683991332331452;2613197102;25.683991332331452 +2022-03-14T00:30:00Z;87.92239831967954;3.080014742522721;8.71652957052786;75221320472.7742;25.687880532885767;2610339311;25.687880532885767 +2022-03-14T00:40:00Z;87.8240349646828;3.026586408089198;8.84931846033539;75217416588.3871;25.69173723097531;2608855040;25.69173723097531 +2022-03-14T00:50:00Z;87.90400712448766;3.0454153386711376;8.77799076270259;75213656678.4;25.69545169488515;2608716899;25.69545169488515 +2022-03-14T01:00:00Z;87.85959029992182;3.112169955721821;8.77435572249757;75209574862.45161;25.699484173875057;2607116817;25.699484173875057 +2022-03-14T01:10:00Z;87.78710454907578;3.0508357470748018;8.891607083004775;75205521738.32259;25.70348830784397;2606627807;25.70348830784397 +2022-03-14T01:20:00Z;87.93935075752488;3.0982537764565463;8.704343543810804;75201276102.19354;25.707682626918032;2604258623;25.707682626918032 +2022-03-14T01:30:00Z;87.56608931127734;3.163652957683612;8.989013128851816;75195407723.35484;25.713480074591097;2603459881;25.713480074591097 +2022-03-14T01:40:00Z;87.86786545937937;3.0571028617077505;8.808842554056643;75191048324.12903;25.717786781706007;2600720846;25.717786781706007 +2022-03-14T01:50:00Z;87.79093131090805;3.0002128471750336;8.926743599538764;75187535401.96721;25.721257243135387;2637465468;25.721257243135387 +2022-03-14T02:00:00Z;87.59327423746447;3.018966293318569;9.11059912248432;75183350565.7705;25.725391497166637;2644551085;25.725391497166637 +2022-03-14T02:10:00Z;87.16749649686639;3.0880734755275836;9.454512575847568;75179653053.93549;25.729044317131603;2642589167;25.729044317131603 +2022-03-14T02:20:00Z;87.6348059109975;3.1059302897708547;8.96550559270635;75174294230.70967;25.734338368196603;2641381112;25.734338368196603 +2022-03-14T02:30:00Z;87.90710936965658;3.0440997944012986;8.754846764196639;75163410894.45161;25.745090157438366;2639515312;25.745090157438366 +2022-03-14T02:40:00Z;87.98811302968348;3.0265693251209207;8.70071414777459;75159582191.48387;25.748872582827264;2637807352;25.748872582827264 +2022-03-14T02:50:00Z;87.68167011081778;3.148044187487331;8.90478373289799;75155561174.70967;25.752844997523326;2637020523;25.752844997523326 +2022-03-14T03:00:00Z;87.80300440594847;3.018679566369084;8.884974064637506;75151929142.55737;25.756433129259296;2636113524;25.756433129259296 +2022-03-14T03:10:00Z;87.60052606042062;3.129202268704257;8.991694066779216;75169468878.45161;25.73910539636386;2634341805;25.73910539636386 +2022-03-14T03:20:00Z;87.16114834259572;3.1193895368344475;9.422480295242472;75166679700.64516;25.741860861344612;2632891161;25.741860861344612 +2022-03-14T03:30:00Z;87.82151989240575;3.063273781249937;8.832648433947497;75160013328.51613;25.748446656953504;2630969310;25.748446656953504 +2022-03-14T03:40:00Z;87.87654051414307;3.123149468566248;8.717126563749668;75206782909.93549;25.70224238002752;2630043780;25.70224238002752 +2022-03-14T03:50:00Z;87.81440115905119;3.123679499632366;8.790340998626094;75208005896.25807;25.701034175955346;2627989306;25.701034175955346 +2022-03-14T04:00:00Z;87.9052196518172;3.0393496718918516;8.768464380160058;75204343741.93549;25.704652065774553;2625701822;25.704652065774553 +2022-03-14T04:10:00Z;87.74973938515602;3.1163907864303346;8.870133529425456;75200359628.8;25.70858802288664;2624037525;25.70858802288664 +2022-03-14T04:20:00Z;87.0493255759461;3.1608480040857763;9.491020029913003;75197498929.54839;25.71141414483197;2622048454;25.71141414483197 +2022-03-14T04:30:00Z;87.73253069215417;3.022896902202406;8.985282776214245;75193645782.70967;25.71522071863847;2620898998;25.71522071863847 +2022-03-14T04:40:00Z;87.6925910931215;3.008128088951394;9.016850075166488;75189664404.64516;25.719153973738425;2619529250;25.719153973738425 +2022-03-14T04:50:00Z;87.88503888832814;3.0160668337676393;8.835491108683991;75185988442.83871;25.722785504150284;2617265383;25.722785504150284 +2022-03-14T05:00:00Z;87.93773022236623;2.9753399502409144;8.821049372756498;75181817050.2295;25.726906477086832;2614997256;25.726906477086832 +2022-03-14T05:10:00Z;87.80878575549008;3.078390006265403;8.819493109380304;75201016732.90323;25.7079388612086;2614390454;25.7079388612086 +2022-03-14T05:20:00Z;87.70962916585982;3.0545493500840624;8.933565542116861;75197511944.25807;25.71140128743125;2612422326;25.71140128743125 +2022-03-14T05:30:00Z;87.45208909327177;3.0692679150254585;9.193855465022596;75191603398.19354;25.71723841682839;2610231560;25.71723841682839 +2022-03-14T05:40:00Z;87.62101996709508;3.070825035683759;9.034325280278308;75187333053.93549;25.72145714538402;2609511642;25.72145714538402 +2022-03-14T05:50:00Z;87.79914026043608;3.097761717495469;8.831216731620994;75183680809.29033;25.725065245304208;2607961944;25.725065245304208 +2022-03-14T06:00:00Z;87.77153004794897;3.0858530946192704;8.851260545658194;75179660808.39345;25.729036656401878;2606211270;25.729036656401878 +2022-03-14T06:10:00Z;87.71345693777688;3.0412818038802403;8.965993940192329;75175824669.37704;25.732826427959825;2605009689;25.732826427959825 +2022-03-14T06:20:00Z;86.97659219137834;3.039251999494479;9.708985101393202;75171945571.09677;25.73665863953251;2603115025;25.73665863953251 +2022-03-14T06:30:00Z;87.79364146152724;3.124759504039522;8.795511495935676;75167971988.64516;25.74058419324521;2601663983;25.74058419324521 +2022-03-14T06:40:00Z;87.73126195458656;3.0526486242713884;8.94121684633913;75164234190.45161;25.74427681262702;2600621039;25.74427681262702 +2022-03-14T06:50:00Z;87.16363076903612;3.0093672100178916;9.555519599551271;75160123458.06451;25.748337858542296;2598954169;25.748337858542296 +2022-03-14T07:00:00Z;87.77277636662977;3.0360522097378175;8.897676567973704;75156580587.01639;25.751837906865422;2597138366;25.751837906865422 +2022-03-14T07:10:00Z;87.22647335569097;3.117843085875157;9.38461788191397;75218918752.5246;25.690253223513828;2595331171;25.690253223513828 +2022-03-14T07:20:00Z;87.65780312203397;3.112606162393353;8.946762157493337;75227201469.93549;25.68207061940793;2594965042;25.68207061940793 +2022-03-14T07:30:00Z;87.43046343306071;3.1003293676764105;9.170859471612246;75220550028.3871;25.688641664902285;2593644544;25.688641664902285 +2022-03-14T07:40:00Z;87.83600316020525;3.0893152538907076;8.795871253792095;75216877237.67741;25.692270062546456;2592538690;25.692270062546456 +2022-03-14T07:50:00Z;87.78504940770985;3.1001024457420474;8.859020550276165;75212789363.6129;25.69630852642797;2591235959;25.69630852642797 +2022-03-14T08:00:00Z;87.80691030561137;3.0566383659165433;8.849433060419969;75209060754.88524;25.69999206741707;2589709279;25.69999206741707 +2022-03-14T08:10:00Z;87.93967031680103;3.001242502347108;8.739485238575346;75205121141.5082;25.70388406263983;2588756100;25.70388406263983 +2022-03-14T08:20:00Z;86.88412533806601;3.0570682175129607;9.756989622416905;75201196032;25.70776172930217;2586873526;25.70776172930217 +2022-03-14T08:30:00Z;87.34499337000477;3.004396713404705;9.305193817194004;75197419718.19354;25.711492398758207;2583930285;25.711492398758207 +2022-03-14T08:40:00Z;87.79945822911338;3.1377449883079063;8.783830898677788;75193305088;25.715557295367102;2582987479;25.715557295367102 +2022-03-14T08:50:00Z;87.76310319605577;3.0820139634520958;8.856617712228648;75189701202.58064;25.719117620580025;2581389983;25.719117620580025 +2022-03-14T09:00:00Z;87.87420779465371;3.053021430471204;8.788034597746602;75185447176.25807;25.723320228435245;2579455802;25.723320228435245 +2022-03-14T09:10:00Z;87.79745800915295;2.990872765932045;8.928235298019905;75181609430.03279;25.727111587775738;2577535174;25.727111587775738 +2022-03-14T09:20:00Z;87.72787704948853;3.0511887580904973;8.935734089772776;75177305715.6129;25.731363283147633;2575011510;25.731363283147633 +2022-03-14T09:30:00Z;87.82948782912734;3.0535758746975517;8.819292712651468;75171333285.16129;25.737263524760515;2602745195;25.737263524760515 +2022-03-14T09:40:00Z;87.76091063125436;2.984208593693108;8.993620715006942;75159187389.93549;25.749262612404575;2619081431;25.749262612404575 +2022-03-14T09:50:00Z;87.7303017933936;3.113223470305334;8.768796578129315;75154971020.3871;25.753428018643508;2617370690;25.753428018643508 +2022-03-14T10:00:00Z;87.70835213820229;3.0602230925627723;8.915622914775035;75151113367.08197;25.75723904444672;2616139373;25.75723904444672 +2022-03-14T10:10:00Z;87.69922818707923;3.1080647343956906;8.923308492449515;75147142309.16129;25.761162104142535;2614388141;25.761162104142535 +2022-03-14T10:20:00Z;86.79799325337153;3.0222506603978925;9.884941334244093;75143411778.06451;25.764847544265045;2612865817;25.764847544265045 +2022-03-14T10:30:00Z;87.6169134885343;3.0767846203132385;9.00249535724624;75139298931.6129;25.76891067869211;2611147214;25.76891067869211 +2022-03-14T10:40:00Z;87.8497346125238;3.0534012734765805;8.803130081761763;75175293654.70967;25.733351024246524;2609656733;25.733351024246524 +2022-03-14T10:50:00Z;87.86090466108557;3.023564284505567;8.848954166546237;75187199537.54839;25.721589047956943;2607673014;25.721589047956943 +2022-03-14T11:00:00Z;87.7959647727563;3.0560725888418876;8.856067025908695;75183770260.64516;25.72497687514897;2606234842;25.72497687514897 +2022-03-14T11:10:00Z;87.71588488354384;3.0295115608577072;8.959164445896583;75202624528.78688;25.706350498773137;2604912310;25.706350498773137 +2022-03-14T11:20:00Z;87.76724494991268;3.0830000355335057;8.8582010292499;75199821790.42622;25.709119360401516;2603135042;25.709119360401516 +2022-03-14T11:30:00Z;87.77157989572484;3.112942755711284;8.80449849133567;75193375710.96774;25.715487526020016;2601607564;25.715487526020016 +2022-03-14T11:40:00Z;87.38496452899905;3.0139740995149205;9.333705952992442;75189513249.03226;25.719303302331614;2599771086;25.719303302331614 +2022-03-14T11:50:00Z;87.36811543722676;3.1090340034778627;9.219534007372305;75185571179.35484;25.72319772416542;2598944570;25.72319772416542 +2022-03-14T12:00:00Z;87.78233391468252;3.150905255550521;8.799814601471702;75181668153.80646;25.727053573797022;2597751379;25.727053573797022 +2022-03-14T12:10:00Z;87.85095106586921;3.0692380971629105;8.784862021210127;75177868981.67741;25.730806825286823;2596313815;25.730806825286823 +2022-03-14T12:20:00Z;87.82359982854678;2.994827739294982;8.905251703203824;75173763709.90164;25.734862476593253;2593997196;25.734862476593253 +2022-03-14T12:30:00Z;87.64405511180063;3.0913690774166196;8.98501655803975;75170200525.63934;25.73838259260449;2592961965;25.73838259260449 +2022-03-14T12:40:00Z;87.05884292650836;3.0984442138926482;9.567926940426592;75166130902.70967;25.74240302595284;2591156819;25.74240302595284 +2022-03-14T12:50:00Z;87.81692786458643;2.994718258614688;8.882180703799945;75162336619.35484;25.74615144775911;2589606229;25.74615144775911 +2022-03-14T13:00:00Z;87.2641650927415;3.0655184367429023;9.401401152944345;75158444032;25.749996985363758;2587434612;25.749996985363758 +2022-03-14T13:10:00Z;87.88151124985212;3.011836992827333;8.837585111942024;75154086152.25807;25.75430219136082;2584734158;25.75430219136082 +2022-03-14T13:20:00Z;87.80261653750863;3.0590721606425015;8.866953135861193;75150344258.06451;25.757998857234227;2583967149;25.757998857234227 +2022-03-14T13:30:00Z;87.78867477499959;3.0349100748357065;8.885057036138635;75143795480.7742;25.764468479374642;2582738812;25.764468479374642 +2022-03-14T13:40:00Z;87.79351601672498;3.0772715356479634;8.838613771844825;75140139734.70967;25.768080038392487;2581449431;25.768080038392487 +2022-03-14T13:50:00Z;87.74588526504851;3.1404765614679375;8.846202018376413;75135945166.45161;25.77222390685354;2579419136;25.77222390685354 +2022-03-14T14:00:00Z;87.87919821866905;3.0833931740300473;8.772496645160334;75129551508.64516;25.778540284441156;2578094919;25.778540284441156 +2022-03-14T14:10:00Z;87.67547551520194;3.153040825074457;8.893398729912363;75153134823.2258;25.755242021667616;2576039606;25.755242021667616 +2022-03-14T14:20:00Z;87.75205716009529;3.0796548025269184;8.889628386785862;75171952375.74193;25.736651917135173;2573899247;25.736651917135173 +2022-03-14T14:30:00Z;87.43643631591537;3.0890121244235806;9.202763728031204;75167775948.8;25.74077786355441;2572065561;25.74077786355441 +2022-03-14T14:40:00Z;86.75936069551466;3.1014689243343683;9.870149840658788;75164013204.64516;25.744495127375373;2569226306;25.744495127375373 +2022-03-14T14:50:00Z;86.70111010502801;3.1111763180361978;9.92636440536352;75160283796.64516;25.748179457976004;2568862753;25.748179457976004 +2022-03-14T15:00:00Z;87.8327085269608;3.104584480540255;8.75830841604343;75156333601.03226;25.752081907526996;2567195598;25.752081907526996 +2022-03-14T15:10:00Z;87.92909488600462;3.0509930020008245;8.761640016921074;75174193944.7742;25.73443744197478;2565309077;25.73443744197478 +2022-03-14T15:20:00Z;87.8646144463883;3.06994509850217;8.790998309975956;75171273034.32259;25.737323047346614;2562635115;25.737323047346614 +2022-03-14T15:30:00Z;87.88862221040982;2.945368122888005;8.885474962300949;75164683537.06667;25.743832897269908;2561895523;25.743832897269908 +2022-03-14T15:40:00Z;87.13074928184308;3.1521586896226004;9.393318199039992;75160846798.45161;25.747623261179157;2560509291;25.747623261179157 +2022-03-14T15:50:00Z;87.69900016272689;3.066953054945986;8.936666621902248;75156789512.25807;25.75163150690567;2559285710;25.75163150690567 +2022-03-14T16:00:00Z;87.64232698973767;3.1353309832416;8.956486919832557;75153013793.03226;25.755361588967762;2557479110;25.755361588967762 +2022-03-14T16:10:00Z;87.6947438526293;3.1506911905819845;8.873186453734954;75148880070.19354;25.75944534744878;2556104435;25.75944534744878 +2022-03-14T16:20:00Z;87.74272524680508;3.012897860001824;8.975089743231127;75144985213.90164;25.763293126565816;2554765444;25.763293126565816 +2022-03-14T16:30:00Z;87.29159348781758;3.1487631442705752;9.246490036729352;75141182893.41936;25.76704948835468;2553352522;25.76704948835468 +2022-03-14T16:40:00Z;86.96479921759082;3.079425698278164;9.67456163263951;75137157186.06451;25.771026536936283;2550502235;25.771026536936283 +2022-03-14T16:50:00Z;87.14006727918313;3.1256475410395144;9.43721123692254;75133178252.3871;25.774957377194458;2549194157;25.774957377194458 +2022-03-14T17:00:00Z;87.65973611326712;3.1725540024316596;8.896908424636583;75129322330.83871;25.77876669217271;2547505945;25.77876669217271 +2022-03-14T17:10:00Z;87.77757076896205;3.0700059150947627;8.88088556241971;75126267111.2258;25.781784983309382;2564555281;25.781784983309382 +2022-03-14T17:20:00Z;87.61636502185246;3.201709990422818;8.911127101608875;75117272361.29033;25.790671013594174;2590704355;25.790671013594174 +2022-03-14T17:30:00Z;87.73461827640756;3.119833192416685;8.873021234458516;75107715891.2;25.800111974515513;2589760611;25.800111974515513 +2022-03-14T17:40:00Z;87.5409433784461;3.0856636964565864;9.106511979334003;75137656501.67741;25.770533256557208;2589826015;25.770533256557208 +2022-03-14T17:50:00Z;87.74367963971055;3.112112691005962;8.86618601124104;75155673484.3871;25.75273404533434;2589166097;25.75273404533434 +2022-03-14T18:00:00Z;87.45314255056162;3.054029279922038;9.193092243410254;75151412719.48387;25.756943310320903;2587275132;25.756943310320903 +2022-03-14T18:10:00Z;87.9169314935953;3.036905879124698;8.77508976697945;75147947965.93549;25.760366185351455;2584509935;25.760366185351455 +2022-03-14T18:20:00Z;87.71695827622382;3.1005631126802595;8.898749652108927;75143718845.93549;25.764544187927125;2583300532;25.764544187927125 +2022-03-14T18:30:00Z;87.81981076585795;3.068252788966227;8.8406631505313;75140110930.58064;25.76810849436566;2581148177;25.76810849436566 +2022-03-14T18:40:00Z;87.9088489121504;3.0304899903685856;8.782631880620487;75136015645.37704;25.772154279807737;2579914422;25.772154279807737 +2022-03-14T18:50:00Z;87.21540500857641;3.022784681501042;9.487524946137336;75132275612.90323;25.77584910646404;2578402073;25.77584910646404 +2022-03-14T19:00:00Z;87.65862225911157;3.1048135887839083;8.975437101819299;75128349795.09677;25.779727472863435;2576240904;25.779727472863435 +2022-03-14T19:10:00Z;87.5313347444192;3.1467596985909747;9.028303863860529;75146134230.70967;25.762157997937763;2575705319;25.762157997937763 +2022-03-14T19:20:00Z;87.87238900833681;3.0470946869117017;8.80696600707345;75143117790.96774;25.76513797793625;2573935666;25.76513797793625 +2022-03-14T19:30:00Z;87.79004525552806;3.0351619668255854;8.869784714569098;75136582236.32787;25.771594537248557;2572774962;25.771594537248557 +2022-03-14T19:40:00Z;87.57272781735695;3.0675433375247474;9.083362764955236;75132907189.67741;25.775225163565914;2570499766;25.775225163565914 +2022-03-14T19:50:00Z;87.6454691525981;3.1153422410210303;8.954731295404555;75128649728;25.779431165252813;2569656056;25.779431165252813 +2022-03-14T20:00:00Z;87.89072465436175;3.0606938078039665;8.750987887629545;75125233003.35484;25.782806591906077;2567488413;25.782806591906077 +2022-03-14T20:10:00Z;87.74179018178204;3.054647915449539;8.893046207195544;75120960941.41936;25.787027017377543;2565424161;25.787027017377543 +2022-03-14T20:20:00Z;87.9711940260046;3.0386734548863155;8.733125456801723;75117369674.32259;25.790574876785705;2563966315;25.790574876785705 +2022-03-14T20:30:00Z;87.83310171069;3.037413631941425;8.862190163467996;75113271560.25807;25.794623456896208;2563368591;25.794623456896208 +2022-03-14T20:40:00Z;87.7194574946379;3.029386269851169;8.965226655662029;75109538295.60655;25.798311597532955;2564568626;25.798311597532955 +2022-03-14T20:50:00Z;87.36338059837085;3.1042635528617257;9.242807180893946;75105589710.45161;25.802212456091617;2564086487;25.802212456091617 +2022-03-14T21:00:00Z;87.07410685464433;3.0466035971211753;9.591018204933993;75101680474.83871;25.806074440726633;2561795898;25.806074440726633 +2022-03-14T21:10:00Z;87.62646885884254;3.1843879770660903;8.903919883425493;75126299813.16129;25.781752676642583;2561364430;25.781752676642583 +2022-03-14T21:20:00Z;87.59247350135166;3.0865553132763006;9.040296407329322;75149196717.41936;25.759132527541798;2559156488;25.759132527541798 +2022-03-14T21:30:00Z;87.67280852835889;3.033776493236153;9.023446762354673;75143182336;25.765074213060576;2557451952;25.765074213060576 +2022-03-14T21:40:00Z;87.95163581022152;3.020036441137144;8.769184643402962;75138877373.93549;25.76932714099681;2555674756;25.76932714099681 +2022-03-14T21:50:00Z;87.72436722052834;3.0778048141865444;8.912014233649895;75135371767.60655;25.77279037501986;2553329135;25.77279037501986 +2022-03-14T22:00:00Z;87.83337030067354;3.1246158147757224;8.74547103721875;75131175440.51613;25.776935981054255;2552032685;25.776935981054255 +2022-03-14T22:10:00Z;87.65035173950294;3.086343430265402;8.94446002300476;75127530859.35484;25.780536510119198;2550477725;25.780536510119198 +2022-03-14T22:20:00Z;87.15823997598902;3.037026061714708;9.514556389961385;75123482425.80646;25.78453601020257;2548909551;25.78453601020257 +2022-03-14T22:30:00Z;87.59739586946655;3.117747180028181;8.983989388632175;75119684442.83871;25.788288086904483;2546775668;25.788288086904483 +2022-03-14T22:40:00Z;87.90530314016279;3.039997995359833;8.745527996278609;75115807578.83871;25.79211809120266;2545079884;25.79211809120266 +2022-03-14T22:50:00Z;87.91138052565063;3.005129400912146;8.81113311221502;75111861936.2623;25.79601604274978;2543112588;25.79601604274978 +2022-03-14T23:00:00Z;87.82667632787096;3.0510387342660565;8.87298143004308;75108107180.06557;25.799725415163177;2541714399;25.799725415163177 +2022-03-14T23:10:00Z;86.91153673920402;3.167207792941085;9.619393166457932;75153974305.03226;25.75441268668786;2539814714;25.75441268668786 +2022-03-14T23:20:00Z;87.86398483858049;3.0871155356931865;8.769316772532497;75151970171.87097;25.75639259586752;2537902344;25.75639259586752 +2022-03-14T23:30:00Z;87.8308271486757;3.0764964385928475;8.84168775403419;75137588785.54839;25.770600154200565;2536168481;25.770600154200565 +2022-03-14T23:40:00Z;87.27591004648903;3.0720244123849443;9.381475543835576;75133413243.87097;25.774725226055498;2534381534;25.774725226055498 +2022-03-14T23:50:00Z;87.40466181169515;3.1048084817686266;9.189275727323855;75129152941.41936;25.778934034180104;2533162337;25.778934034180104 +2022-03-15T00:00:00Z;87.80678179741213;3.013982487253059;8.896916421928806;75125584274.88524;25.782459566198877;2531332757;25.782459566198877 +2022-03-15T00:10:00Z;87.90246738815172;3.0364847197502782;8.78341031301032;75121681573.16129;25.78631509592014;2530117698;25.78631509592014 +2022-03-15T00:20:00Z;87.95698131407309;2.9992486267053247;8.754737100091681;75117973305.80646;25.789978541402846;2528683107;25.789978541402846 +2022-03-15T00:30:00Z;87.91066551299826;3.152538580214356;8.688204789837608;75114053169.54839;25.793851294926792;2526523656;25.793851294926792 +2022-03-15T00:40:00Z;87.86499757360004;3.0718945529487534;8.792548740478836;75133491332.12903;25.774648081651137;2524401862;25.774648081651137 +2022-03-15T00:50:00Z;87.5428503098968;3.1338834859234175;9.026175054879657;75162048512;25.746436072756897;2535028300;25.746436072756897 +2022-03-15T01:00:00Z;87.87688238781735;3.0704132964711186;8.780849112509024;75157972199.2258;25.750463115089527;2569868982;25.750463115089527 +2022-03-15T01:10:00Z;87.57787431881806;3.0024230874253606;9.145052243573529;75153908599.46666;25.75447759806948;2568664890;25.75447759806948 +2022-03-15T01:20:00Z;84.49731991424474;3.2471401324441405;11.871652258986312;75153088379.87097;25.75528790366106;2566853335;25.75528790366106 +2022-03-15T01:30:00Z;87.15555018318908;3.110719356311301;9.4505132476786;75150185372.90323;25.758155821948655;2566234641;25.758155821948655 +2022-03-15T01:40:00Z;87.64226638977962;3.0489484803159637;9.034459812635356;75145864753.54839;25.762424217925368;2564912359;25.762424217925368 +2022-03-15T01:50:00Z;87.58913353783626;3.1045557504026564;9.045947052985273;75142113742.45161;25.766129890505873;2563424785;25.766129890505873 +2022-03-15T02:00:00Z;87.52783829661908;3.1239663146536674;9.043130080390766;75138102503.2258;25.770092645834897;2561345435;25.770092645834897 +2022-03-15T02:10:00Z;87.36572576753477;3.072534143262756;9.273793102957985;75134008419.09677;25.774137244719793;2559952830;25.774137244719793 +2022-03-15T02:20:00Z;87.36285776484888;3.119238142697621;9.233609827450909;75130347788.59016;25.77775362914143;2558648584;25.77775362914143 +2022-03-15T02:30:00Z;87.7728839986535;3.0423801761412594;8.877892241680406;75126162531.09677;25.781888299377133;2557436102;25.781888299377133 +2022-03-15T02:40:00Z;87.6977121291612;3.1373330494607514;8.878002131901209;75122386745.80646;25.78561844670523;2555242694;25.78561844670523 +2022-03-15T02:50:00Z;87.52314259570093;3.208346033319437;8.98721790404352;75118446856.25807;25.789510714761242;2553040301;25.789510714761242 +2022-03-15T03:00:00Z;87.66154359149591;3.083649467576334;8.984178999844586;75114282413.41936;25.793624821929242;2552061616;25.793624821929242 +2022-03-15T03:10:00Z;87.50092848028942;3.081225496052936;9.144416691192891;75132495475.6129;25.77563190123758;2550246350;25.77563190123758 +2022-03-15T03:20:00Z;87.70608537905368;3.033556919498062;8.985192635524529;75128915464.39345;25.77916864081835;2548756414;25.77916864081835 +2022-03-15T03:30:00Z;87.33456793760351;3.183763802575478;9.205157925723821;75122932901.16129;25.785078892736735;2545687453;25.785078892736735 +2022-03-15T03:40:00Z;87.18628754354357;3.073665747518722;9.440773949238874;75118635536.51613;25.789324315083714;2545076885;25.789324315083714 +2022-03-15T03:50:00Z;87.69082301469014;3.072878717193037;8.962744692785234;75114967700.64516;25.79294781777839;2543529654;25.79294781777839 +2022-03-15T04:00:00Z;87.73554716311;3.026107665793405;8.95867018387689;75110920390.19354;25.79694620833986;2541750404;25.79694620833986 +2022-03-15T04:10:00Z;87.0050000394743;3.1075491962808526;9.59649184139059;75135222618.83871;25.772937721024753;2540445562;25.772937721024753 +2022-03-15T04:20:00Z;87.66342050490283;3.092450955670107;8.963385029221755;75161356221.93549;25.74711999510307;2537700121;25.74711999510307 +2022-03-15T04:30:00Z;87.58955356739028;3.0560248698676635;9.059501765089292;75157354260.98361;25.751073584304766;2536365948;25.751073584304766 +2022-03-15T04:40:00Z;87.76178440641634;3.0699441128505547;8.897240068637645;75153630241.03226;25.75475259198215;2534815149;25.75475259198215 +2022-03-15T04:50:00Z;87.79044310940645;3.0745377934708955;8.87125419672842;75149493809.54839;25.758839026368896;2533346601;25.758839026368896 +2022-03-15T05:00:00Z;87.69907158032143;3.145909791318542;8.863312726564391;75138751058.58064;25.76945192957644;2531602894;25.76945192957644 +2022-03-15T05:10:00Z;87.19461975222282;3.0671868558269266;9.438294295997997;75134083798.70967;25.77406277622119;2531048217;25.77406277622119 +2022-03-15T05:20:00Z;87.90286455187912;3.039997206029209;8.78506650349279;75130618648.7742;25.777486042847706;2529928041;25.777486042847706 +2022-03-15T05:30:00Z;87.7291629471114;3.078882942759133;8.91975115163191;75123940583.2258;25.784083390537464;2529124154;25.784083390537464 +2022-03-15T05:40:00Z;87.89280066316886;3.03409629524877;8.802898800844881;75120198504.91803;25.787780238299693;2528143030;25.787780238299693 +2022-03-15T05:50:00Z;87.03128989812812;3.0892359097282145;9.605094154824549;75116164789.67741;25.791765197975657;2526305908;25.791765197975657 +2022-03-15T06:00:00Z;87.53804713710032;3.030695653094052;9.14318435796781;75112347185.54839;25.795536658677644;2524485500;25.795536658677644 +2022-03-15T06:10:00Z;87.4609719918427;3.0518036838150464;9.200236657131843;75108432730.83871;25.799403799326157;2522805347;25.799403799326157 +2022-03-15T06:20:00Z;87.82553689430381;3.056887634115634;8.83828332778473;75104472559.48387;25.80331610404217;2521699244;25.80331610404217 +2022-03-15T06:30:00Z;87.7184453517978;3.119368425958046;8.883974938277358;75100714875.87097;25.80702836848803;2519335573;25.80702836848803 +2022-03-15T06:40:00Z;87.6688022687559;3.0636001344611086;8.987028987445077;75096629919.4754;25.81106394996649;2518642027;25.81106394996649 +2022-03-15T06:50:00Z;87.75889071109071;3.0902505354536993;8.851400132586855;75093006534.19354;25.81464353934685;2517770967;25.81464353934685 +2022-03-15T07:00:00Z;87.77103437057814;3.018095215642878;8.930706733298269;75088746429.93549;25.818852151673482;2515904644;25.818852151673482 +2022-03-15T07:10:00Z;87.23010363420101;3.070673499932841;9.406612258284495;75107290078.96774;25.8005326399502;2513786219;25.8005326399502 +2022-03-15T07:20:00Z;87.65530603044218;3.127419519321831;8.929818254259475;75103736997.16129;25.80404277561411;2512495121;25.80404277561411 +2022-03-15T07:30:00Z;87.69481920352345;3.0000823492368403;9.043854238513585;75097719312.51613;25.80998772443256;2510841378;25.80998772443256 +2022-03-15T07:40:00Z;87.60787697099407;3.1341148313369893;8.973348513625883;75115103397.16129;25.79281376142767;2508344419;25.79281376142767 +2022-03-15T07:50:00Z;87.66319524045508;3.0707823587417624;8.98343089147733;75145568994.62296;25.762716402009115;2506211989;25.762716402009115 +2022-03-15T08:00:00Z;87.35016582934949;3.1290192483658585;9.255599958117225;75141410617.80646;25.76682451647499;2503656019;25.76682451647499 +2022-03-15T08:10:00Z;86.7370125713568;3.062044703573163;9.923871408645269;75137793453.41936;25.77039796015262;2503089515;25.77039796015262 +2022-03-15T08:20:00Z;87.68512599515593;3.0860358826664327;8.943209691680067;75133797276.90323;25.77434583483512;2501241294;25.77434583483512 +2022-03-15T08:30:00Z;87.57353076114937;3.1745315409645225;8.967989864295339;75129831357.93549;25.77826381769257;2502231426;25.77826381769257 +2022-03-15T08:40:00Z;87.86972958487418;3.01894068329679;8.828630629834844;75125868279.74193;25.78217899411232;2545188058;25.78217899411232 +2022-03-15T08:50:00Z;87.5416662224899;3.118668602154672;9.067812285401882;75122189741.41936;25.785813069897927;2542616312;25.785813069897927 +2022-03-15T09:00:00Z;87.67177763789846;3.0451154737317427;8.984679637208856;75118100882.88524;25.78985250634973;2541758068;25.78985250634973 +2022-03-15T09:10:00Z;87.31296115034144;3.06927988042266;9.337180221322138;75113810118.19354;25.794091408516987;2540330149;25.794091408516987 +2022-03-15T09:20:00Z;87.63746633296266;3.0408890836387394;9.050369488426401;75110041864.25807;25.797814115521803;2538676224;25.797814115521803 +2022-03-15T09:30:00Z;87.28498780646251;3.0876176687063404;9.303920108943064;75103661551.48387;25.804117309378714;2536571937;25.804117309378714 +2022-03-15T09:40:00Z;87.80600493823432;3.0364335028121783;8.887595500340177;75099720869.16129;25.808010360626653;2536404378;25.808010360626653 +2022-03-15T09:50:00Z;87.684766742093;3.0670933637939153;8.97190891264302;75095796819.93443;25.811886979823296;2534782910;25.811886979823296 +2022-03-15T10:00:00Z;87.80432803965883;3.0176203067268554;8.882267286809135;75091800399.7377;25.815835095241003;2533919381;25.815835095241003 +2022-03-15T10:10:00Z;86.77515401565314;3.056472795717131;9.8503177197876;75088042446.45161;25.819547626100512;2531771954;25.819547626100512 +2022-03-15T10:20:00Z;87.68270478475662;3.050361566661972;8.994017793046632;75084185269.67741;25.823358181132622;2530906574;25.823358181132622 +2022-03-15T10:30:00Z;87.2679755025459;3.044718335302369;9.417102822181421;75080236395.35484;25.827259325363755;2529321422;25.827259325363755 +2022-03-15T10:40:00Z;87.71807177346045;3.0482426365104;8.93941615381553;75076302848;25.83114532788438;2527349000;25.83114532788438 +2022-03-15T10:50:00Z;87.86046468041495;3.019277535675456;8.820375021183548;75072332965.16129;25.83506722670145;2525569225;25.83506722670145 +2022-03-15T11:00:00Z;87.77609099766798;3.004242017626859;8.94443690706336;75066770885.2459;25.84056207768998;2522786981;25.84056207768998 +2022-03-15T11:10:00Z;87.70834514071545;3.0945516432548805;8.929829751345423;75094995145.44263;25.81267896446586;2522404137;25.81267896446586 \ No newline at end of file diff --git a/test_input_data/usage_idle_data.csv b/test_input_data/usage_idle_data.csv index 184ee4f..4426352 100644 --- a/test_input_data/usage_idle_data.csv +++ b/test_input_data/usage_idle_data.csv @@ -1392,4 +1392,4 @@ _time;_value 2021-11-17T11:00:00Z;96.22618296114042 2021-11-17T12:00:00Z;96.18600928188728 2021-11-17T13:00:00Z;96.11710448444755 -2021-11-17T14:00:00Z;95.86516970627649 +2021-11-17T14:00:00Z;95.86516970627649 \ No newline at end of file diff --git a/tox.ini b/tox.ini index 2580382..c0bbff1 100644 --- a/tox.ini +++ b/tox.ini @@ -8,4 +8,4 @@ deps=-r{toxinidir}/requirements.txt {toxinidir} commands= - pytest --cov=src\psl + pytest --cov=src\psl \ No newline at end of file -- GitLab